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?

War es hilfreich?

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.

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

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top