Welche Anmerkung soll ich verwenden: @IdClass oder @EmbeddedId
-
03-07-2019 - |
Frage
Die JPA
(Java Persistence API) Spezifikation hat 2 verschiedene Arten Einheit zusammengesetzte Schlüssel angeben: @IdClass
und @EmbeddedId
.
Ich verwende beide Anmerkungen auf meine abgebildet Einheiten, aber es stellt sich heraus, ein großes Durcheinander, um Menschen zu sein, die mit JPA
nicht sehr vertraut sind.
Ich möchte nur einen Weg adoptieren zusammengesetzte Schlüssel zu spezifizieren. Welches ist wirklich die beste? Warum?
Lösung
Ich denke, dass @EmbeddedId
wahrscheinlich, weil mit @IdClass
ausführlicher ist, dass Sie nicht das gesamte Primärschlüssel Objekt mit einem beliebigen Feld Zugang Betreibern zugreifen können. Mit Hilfe der @EmbeddedId
Sie können wie folgt tun:
@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
@EmbeddedId EmployeeId employeeId;
...
}
Es wird eine klare Vorstellung von den Bereichen, die den zusammengesetzten Schlüssel zu machen, weil sie alle in einer Klasse zusammengefasst werden, die Trog ein Feld Zugriffsoperator zugegriffen wird.
Ein weiterer Unterschied mit @IdClass
und @EmbeddedId
wird, wenn es darum geht, HQL zu schreiben:
Mit @IdClass
schreiben Sie:
select e.name from Employee e
und mit @EmbeddedId
Sie schreiben:
select e.employeeId.name from Employee e
Sie müssen mehr Text für die gleiche Abfrage schreiben. Manche mögen argumentieren, dass dies unterscheidet sich von einer natürlichen Sprache wie die von IdClass
gefördert. Aber die meisten der Zeit direkt aus der Abfrage zu verstehen, dass ein bestimmtes Feld Teil des zusammengesetzten Schlüssels ist, ist von unschätzbarem Wert.
Andere Tipps
Ich entdeckte eine Instanz, wo ich musste EmbeddedId statt IdClass. In diesem Szenario ist eine dort Join-Tabelle, die definiert zusätzliche Spalten. Ich habe versucht, dieses Problem zu lösen IdClass mit dem Schlüssel eines Unternehmens darstellen, die Zeilen in der Join-Tabelle explizit darstellt. Ich konnte es nicht auf diese Weise zu arbeiten. Zum Glück hat einen Abschnitt zu diesem Thema gewidmet „Java Persistence mit Hibernate“. Eine vorgeschlagene Lösung war sehr ähnlich wie mir, aber es verwendet EmbeddedId statt. Ich modellierte meine Objekte nach denen in dem Buch jetzt ist es korrekt verhält.
Es gibt drei Strategien, um eine Verbindung Primärschlüssel zu verwenden:
- Mark als
@Embeddable
und fügen Sie eine normale Eigenschaft für sie zu Ihrer Entity-Klasse, die mit@Id
. - in Ihre Entitätsklasse eine normale Eigenschaft für sie, mit
@EmbeddedId
markiert. - Fügen Sie Objekte zu Ihren Entitätsklasse für alle seine Felder, so dass sie mit
@Id
markieren und Ihre Entity-Klasse mit@IdClass
markieren, die Klasse Ihrer Primärschlüsselklasse zu liefern.
Die Verwendung von @Id
mit einer Klasse als @Embeddable
markiert ist der natürlichste Ansatz. Der @Embeddable
Tag kann ohnehin für Nicht-Primärschlüssel embeddable Werte verwendet werden. Es ermöglicht Ihnen die Verbindung Primärschlüssel als eine einzige Eigenschaft zu behandeln, und es erlaubt die Wiederverwendung der @Embeddable
Klasse in anderen Tabellen.
Der nächste natürlichste Ansatz ist die Verwendung des @EmbeddedId
-Tag. Hier wird die Primärschlüsselklasse kann nicht in anderen Tabellen verwendet werden, da es keine @Embeddable
Einheit ist, aber es erlaubt uns den Schlüssel als zu behandeln
einzelnes Attribut einer Klasse.
Schließlich ist die Verwendung der @IdClass
und @Id
Anmerkungen können wir die Verbindung Primärschlüsselklasse mit Eigenschaften der Entität selbst auf die Namen der Eigenschaften in der Primärschlüsselklasse entsprechend abzubilden. Die Namen müssen entsprechen (es gibt keinen Mechanismus, um dies für das Überschreiben) und die Primärschlüssel-Klasse müssen die gleichen Verpflichtungen wie bei den anderen beiden Techniken würdigen. Der einzige Vorteil dieses Ansatzes ist seine Fähigkeit, die Nutzung der Primärschlüssel-Klasse von der Schnittstelle des einschließenden Einheit zu „verstecken“. Die @IdClass
Annotation Parameter nimmt einen Wert von Klasse-Typ, die die Klasse als Verbindung Primärschlüssel verwendet werden muss. Die Felder, die auf die Eigenschaften der Primärschlüsselklasse entsprechen verwendet werden, müssen alle mit @Id
mit Anmerkungen versehen werden.
Soweit ich weiß, wenn Ihr Composite PK enthält FK ist es einfacher und unkomplizierter @IdClass
verwenden
Mit @EmbeddedId
haben Sie Mapping für Ihre FK Spalte zweimal zu definieren, onece in @Embeddedable
und einmal für so heißt @ManyToOne
wo @ManyToOne
werden muss, schreibgeschützt (@PrimaryKeyJoinColumn
), weil Sie nicht eine Spalte in zwei Variablen gesetzt haben (möglich Konflikte).
So müssen Sie Ihre FK mit einfacher Art in @Embeddedable
eingestellt.
Auf der anderen Seite, diese Situation mit @IdClass
kann viel einfacher gehandhabt wird wie in Primärschlüssel durch OneToOne und ManyToOne Beziehungen :
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 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;
}
}
Ich denke, der Hauptvorteil ist, dass wir @GeneratedValue
für die ID verwenden könnten, wenn die @IdClass
verwenden? Ich bin sicher, dass wir nicht @GeneratedValue
für @EmbeddedId
verwenden können.
Composite-Key darf keine @Id
Eigenschaft hat, wenn @EmbeddedId
verwendet wird.
Mit EmbeddedId können Sie die In-Klausel in HQL verwenden, zum Beispiel: FROM Entity WHERE id IN :ids
wobei id ein EmbeddedId ist, während es Schmerz ist das gleiche Ergebnis mit IdClass erreichen Sie so etwas wie FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN
tun wollen