it-swarm.com.de

Welche Anmerkung sollte ich verwenden: @IdClass oder @EmbeddedId

Die JPA (Java Persistence API) -Spezifikation verfügt über zwei verschiedene Arten, um zusammengesetzte Entitätsschlüssel anzugeben: @IdClass und @EmbeddedId

Ich verwende beide Anmerkungen für meine zugeordneten Entitäten, aber es stellt sich als ein großes Chaos für Leute heraus, die sich mit JPA nicht auskennen. 

Ich möchte nur eine Möglichkeit verwenden, um zusammengesetzte Schlüssel anzugeben. Welches ist wirklich das Beste? Warum?

110
sakana

Ich denke, dass @EmbeddedId wahrscheinlich ausführlicher ist, da Sie mit @IdClass nicht auf das gesamte Primärschlüsselobjekt mit einem Feldzugriffsoperator zugreifen können. Mit dem @EmbeddedId kannst du folgendes machen:

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

Dies gibt eine klare Vorstellung von den Feldern, aus denen der zusammengesetzte Schlüssel besteht, da sie alle in einer Klasse zusammengefasst sind, auf die über einen Feldzugriffsoperator zugegriffen wird.

Ein weiterer Unterschied zu @IdClass und @EmbeddedId besteht im Schreiben von HQL:

Mit @IdClass schreiben Sie:

@EmbeddedId musst du schreiben:

IdClass gefördert wird. Meistens ist es jedoch von unschätzbarem Wert, wenn man von der Abfrage aus versteht, dass ein bestimmtes Feld Teil des zusammengesetzten Schlüssels ist.

77
Jorge Ferreira

Ich entdeckte eine Instanz, bei der ich EmbeddedId anstelle von IdClass verwenden musste. In diesem Szenario gibt es eine Join-Tabelle, in der zusätzliche Spalten definiert sind. Ich habe versucht, dieses Problem mithilfe von IdClass zu lösen, um den Schlüssel einer Entität darzustellen, die explizit Zeilen in der Join-Tabelle darstellt. Ich konnte es nicht so funktionieren. Glücklicherweise hat "Java Persistence With Hibernate" einen Abschnitt zu diesem Thema. Eine vorgeschlagene Lösung war meiner sehr ähnlich, verwendete jedoch stattdessen EmbeddedId. Ich habe meine Objekte nach denen im Buch modelliert, die sich jetzt korrekt verhalten.

17
laz

Es gibt drei Strategien, um einen zusammengesetzten Primärschlüssel zu verwenden: 

  • Markieren Sie es als @Embeddable und fügen Sie zu Ihrer Entitätsklasse eine normale Eigenschaft hinzu, die mit @Id markiert ist.
  • Fügen Sie Ihrer Entitätsklasse eine normale Eigenschaft hinzu, die mit @EmbeddedId markiert ist.
  • Fügen Sie Ihrer Entitätsklasse Eigenschaften für alle Felder hinzu, markieren Sie sie mit @Id und markieren Sie Ihre Entitätsklasse mit @IdClass, wobei Sie die Klasse Ihrer Primärschlüsselklasse angeben.

Die Verwendung von @Id mit einer Klasse, die als @Embeddable markiert ist, ist der natürlichste Ansatz. Das @Embeddable-Tag kann trotzdem für einbettbare Werte für Nicht-Primärschlüssel verwendet werden. Sie können den zusammengesetzten Primärschlüssel als eine einzige Eigenschaft behandeln und die Wiederverwendung der Klasse @Embeddable in anderen Tabellen zulassen. 

Der nächst natürlichste Ansatz ist die Verwendung des @EmbeddedId-Tags. Hier kann die Primärschlüsselklasse nicht in anderen Tabellen verwendet werden, da es sich nicht um eine @Embeddable-Entität handelt, es ist jedoch möglich, den Schlüssel als ein einzelnes Attribut einer Klasse zu behandeln. 

Durch die Verwendung der Annotationen @IdClass und @Id können wir schließlich die zusammengesetzte Primärschlüsselklasse mit Eigenschaften der Entität selbst abbilden, die den Namen der Eigenschaften in der Primärschlüsselklasse entsprechen. Die Namen müssen übereinstimmen (es gibt keinen Mechanismus, um dies zu überschreiben), und die Primärschlüsselklasse muss die gleichen Verpflichtungen erfüllen wie bei den beiden anderen Techniken. Der einzige Vorteil dieses Ansatzes ist die Möglichkeit, die Verwendung der Primärschlüsselklasse vor der Schnittstelle der umgebenden Entität zu "verbergen". Die Annotation @IdClass verwendet einen Werteparameter vom Typ Class, der die Klasse sein muss, die als zusammengesetzter Primärschlüssel verwendet werden soll. Die Felder, die den Eigenschaften der zu verwendenden Primärschlüsselklasse entsprechen, müssen alle mit @Id versehen werden.

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

13
Adelin

Soweit ich weiß, ob Ihre zusammengesetzte PK FK enthält, ist die Verwendung von @IdClass einfacher und unkomplizierter.

Mit @EmbeddedId müssen Sie das Mapping für Ihre FK-Spalte zweimal definieren, einmal in @Embeddedable und einmal für d. H. @ManyToOne, wobei @ManyToOne schreibgeschützt sein muss (@PrimaryKeyJoinColumn), da in zwei Variablen keine Spalte gesetzt werden kann (mögliche Konflikte).
Sie müssen also Ihren FK mit dem einfachen Typ in @Embeddedable einstellen.

Auf der anderen Site, die @IdClass verwendet, kann diese Situation viel einfacher gehandhabt werden, wie in Primärschlüssel durch OneToOne- und ManyToOne-Beziehungen gezeigt :

Beispiel-JPA 2.0-ManyToOne-ID-Anmerkung

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

    @Id
    private String type;

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

Beispiel einer JPA 2.0-ID-Klasse

...
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;
    }
}
11
Ondrej Bozek

Ich denke, der Hauptvorteil ist, dass wir @GeneratedValue für die ID verwenden könnten, wenn Sie den @IdClass verwenden. Ich bin mir sicher, dass wir @GeneratedValue nicht für @EmbeddedId verwenden können.

6
bertie

Composite Key darf bei Verwendung von @Id keine @EmbeddedId-Eigenschaft haben 

4
B.K

Mit EmbeddedId können Sie die IN-Klausel in HQL verwenden, zum Beispiel: FROM Entity WHERE id IN :ids Dabei ist id eine EmbeddedId, wohingegen es bei IdClass sehr schwer ist, das gleiche Ergebnis zu erzielen wie FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN

0
Aleks Ben Maza