2011-08-25 10 views
8

Sono asking and answering my own question, ma non sto dando per scontato che io abbia la risposta migliore. Se ne hai uno migliore, per favore postalo!Come creare una chiave primaria composta che contiene un attributo @ManyToOne come un @EmbeddedId in JPA?

domande correlate:

Ho un paio di classi che si trovano in una semplice relazione di aggregazione (?): Qualsiasi istanza di uno possiede un certo numero di istanze dell'altro. La classe proprietaria ha una sorta di chiave primaria a sé stante, e la classe posseduta ha una classe a molti a questa classe tramite una chiave esterna corrispondente. Vorrei che la classe posseduta avesse una chiave primaria comprendente quella chiave esterna più alcune informazioni aggiuntive.

Per amor di discussione, usiamo quei preferiti perenni, Ordine e OrdineLinea.

Lo SQL simile a questa:

-- 'order' may have been a poor choice of name, given that it's an SQL keyword! 
create table Order_ (
    orderId integer primary key 
); 
create table OrderLine (
    orderId integer not null references Order_, 
    lineNo integer not null, 
    primary key (orderId, lineNo) 
); 

vorrei mappare questo in Java utilizzando JPA. L'ordine è banale e OrderLine può essere gestito con un @IdClass. Here's the code for that - il codice è abbastanza convenzionale, e spero che perdonerai le mie idiosincrasie.

Tuttavia, l'utilizzo di @IdClass implica la scrittura di una classe ID che duplica i campi nell'Ordine. Vorrei evitare questa duplicazione, quindi preferisco usare @EmbeddedId.

Tuttavia, un tentativo ingenuo per fare questo non riesce:

@Embeddable 
public class OrderLineKey { 
    @ManyToOne 
    private Order order; 
    private int lineNo; 
} 

OpenJPA rifiuta l'uso di tale come EmbeddedId. Non ho provato altri provider, ma non mi aspetto che abbiano successo, perché la specifica JPA richiede che i campi che costituiscono una classe ID siano fondamentali, non le relazioni.

Quindi, cosa posso fare? Come posso scrivere una classe la cui chiave contiene la relazione @ManyToOne, ma è gestita come un @EmbeddedId?

risposta

16

Non conosco un modo per farlo che non implichi la duplicazione di campi (scusate!). Ma può essere fatto in un modo semplice e standardizzato che implica la duplicazione solo dei campi di relazione. La chiave è la @MapsId annotazioni introdotto nel JPA 2.

Il integrabile classe chiave assomiglia a questo:

@Embeddable 
public class OrderLineKey { 
    private int orderId; 
    private int lineNo; 
} 

E la classe di entità embedding si presenta così:

@Entity 
public class OrderLine{ 
    @EmbeddedId 
    private OrderLineKey id; 

    @ManyToOne 
    @MapsId("orderId") 
    private Order order; 
} 

L'annotazione @MapsId dichiara che il campo della relazione a cui è applicato rimodella efficacemente un campo base dall'ID incorporato.

Here's the code for OrderId.

+9

E se l'entità a cui si desidera riferirsi ha una chiave composta?Puoi utilizzare MapsId su più colonne nell'ID incorporato? –

Problemi correlati