Domanda

La specifica JPA (Java Persistence API) ha 2 modi diversi per specificare le chiavi composte dell'entità: @IdClass e @EmbeddedId .

Sto usando entrambe le annotazioni sulle mie entità mappate, ma risulta essere un gran casino per le persone che non hanno molta familiarità con JPA .

Voglio adottare un solo modo per specificare le chiavi composite. Qual è davvero il migliore? Perché?

È stato utile?

Soluzione

Ritengo che @EmbeddedId sia probabilmente più dettagliato perché con @IdClass non è possibile accedere all'intero oggetto chiave primaria utilizzando alcun operatore di accesso al campo. Usando @EmbeddedId puoi fare così:

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

Ciò fornisce una chiara idea dei campi che compongono la chiave composita perché sono tutti aggregati in una classe a cui si accede tramite un operatore di accesso al campo.

Un'altra differenza con @IdClass e @EmbeddedId è quando si tratta di scrivere HQL:

Con @IdClass scrivi:

select e.name from Employee e

e con @EmbeddedId devi scrivere:

select e.employeeId.name from Employee e

Devi scrivere più testo per la stessa query. Alcuni potrebbero sostenere che questo differisce da un linguaggio più naturale come quello promosso da IdClass . Ma la maggior parte delle volte capire dalla query che un determinato campo fa parte della chiave composita è di aiuto inestimabile.

Altri suggerimenti

Ho scoperto un'istanza in cui ho dovuto usare EmbeddedId invece di IdClass. In questo scenario è presente una tabella di join in cui sono definite colonne aggiuntive. Ho tentato di risolvere questo problema utilizzando IdClass per rappresentare la chiave di un'entità che rappresenta esplicitamente le righe nella tabella di join. Non riuscivo a farlo funzionare in questo modo. Per fortuna "Persistenza Java con ibernazione" ha una sezione dedicata a questo argomento. Una soluzione proposta era molto simile alla mia ma utilizzava invece EmbeddedId. Ho modellato i miei oggetti sulla base di quelli nel libro che ora si comporta correttamente.

Esistono tre strategie per utilizzare una chiave primaria composta:

  • Contrassegnalo come @Embeddable e aggiungi alla tua classe di entità una proprietà normale, contrassegnata con @Id .
  • Aggiungi alla tua classe di entità una proprietà normale, contrassegnata con @EmbeddedId .
  • Aggiungi proprietà alla tua classe di entità per tutti i suoi campi, contrassegnale con @Id e contrassegna la tua classe di entità con @IdClass , fornendo la classe del tuo primario classe chiave.

L'uso di @Id con una classe contrassegnata come @Embeddable è l'approccio più naturale. Il tag @Embeddable può comunque essere utilizzato per i valori incorporabili della chiave non primaria. Ti consente di trattare la chiave primaria composta come una singola proprietà e consente il riutilizzo della classe @Embeddable in altre tabelle.

Il prossimo approccio più naturale è l'uso del tag @EmbeddedId . In questo caso, la classe chiave primaria non può essere utilizzata in altre tabelle poiché non è un'entità @Embeddable , ma ci consente di trattare la chiave come un unico attributo di qualche classe.

Infine, l'uso delle annotazioni @IdClass e @Id ci consente di mappare la classe di chiave primaria composta usando le proprietà dell'entità stessa corrispondenti ai nomi della proprietà nella classe chiave primaria. I nomi devono corrispondere (non esiste alcun meccanismo per sovrascriverlo) e la classe chiave primaria deve rispettare gli stessi obblighi delle altre due tecniche. L'unico vantaggio di questo approccio è la sua capacità di & # 8220; nascondere & # 8221; l'uso della classe di chiave primaria dall'interfaccia dell'entità che lo racchiude. L'annotazione @IdClass accetta un parametro value del tipo Class, che deve essere la classe da utilizzare come chiave primaria composta. I campi che corrispondono alle proprietà della classe di chiave primaria da utilizzare devono essere tutti annotati con @Id .

Riferimento: http://www.apress.com/us/book/9781430228509

Per quanto ne so se il tuo PK composito contiene FK è più facile e più semplice usare @IdClass

Con @EmbeddedId devi definire il mapping per la tua colonna FK due volte, quindi in @Embeddedable e una volta per esempio come @ManyToOne dove @ManyToOne deve essere di sola lettura ( @PrimaryKeyJoinColumn ) perché non è possibile impostare una colonna in due variabili (possibili conflitti).
Quindi devi impostare il tuo FK usando il tipo semplice in @Embeddedable .

Sull'altro sito che utilizza @IdClass questa situazione può essere gestita molto più facilmente, come mostrato in Chiavi primarie tramite relazioni OneToOne e ManyToOne :

Esempio annotazione ID ManyToOne JPA 2.0

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

Esempio classe ID JPA 2.0

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}

Penso che il vantaggio principale sia che potremmo usare @GeneratedValue per l'id quando si usa @IdClass ? Sono sicuro che non possiamo usare @GeneratedValue per @EmbeddedId .

La chiave composita non deve avere una proprietà @Id quando si utilizza @EmbeddedId .

Con EmbeddedId puoi usare la clausola IN in HQL, ad esempio: FROM Entity DOVE id IN: ids dove id è un EmbeddedId mentre è difficile ottenere lo stesso risultato con IdClass che vorrai fai qualcosa come DA Entità DOVE idPartA =: idPartA0 AND idPartB =: idPartB0 .... OR idPartA =: idPartAN AND idPartB =: idPartBN

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top