Zusammengesetzte Primärschlüssel in JPA
Einführung
In diesem Tutorial erfahren Sie mehr über zusammengesetzte Primärschlüssel und die entsprechenden Anmerkungen in JPA.
Zusammengesetzte Primärschlüssel
Ein zusammengesetzter Primärschlüssel – auch zusammengesetzter Schlüssel genannt – ist eine Kombination aus zwei oder mehr Spalten, um einen Primärschlüssel für eine Tabelle zu bilden.
In JPA haben wir zwei Möglichkeiten, die zusammengesetzten Schlüssel zu definieren: Die Annotationen @IdClass und @EmbeddedId .
Um die zusammengesetzten Primärschlüssel zu definieren, sollten wir einige Regeln befolgen:
- Die zusammengesetzte Primärschlüsselklasse muss öffentlich sein
- Es muss einen No-arg Konstruktor haben
- Es muss die Methoden equals() und hashCode() definieren
- Es muss serialisierbar sein
Die IdClass Annotation
Sagen wir wir haben eine Tabelle namens Account mit zwei Spalten – AccountNumber, AccountType –, die den zusammengesetzten Schlüssel bilden. Jetzt müssen wir es in JPA abbilden.
Gemäß der JPA-Spezifikation erstellen wir eine AccountId-Klasse mit diesen Primärschlüsselfeldern:
public class AccountId implements Serializable { private String accountNumber; private String accountType; // default constructor public AccountId(String accountNumber, String accountType) { this.accountNumber = accountNumber; this.accountType = accountType; } // equals() and hashCode()}
Als nächstes verknüpfen wir die AccountId-Klasse mit dem Entitätskonto.
Dazu müssen wir die Entität mit der @IdClass Annotation @IdClass . Wir müssen auch die Felder aus der AccountId-Klasse im Entitätskonto deklarieren und sie mit @Id kommentieren:
@Entity@IdClass(AccountId.class)public class Account { @Id private String accountNumber; @Id private String accountType; // other fields, getters and setters}
Die EmbeddedId-Annotation
@EmbeddedId ist eine Alternative zur Annotation @IdClass.
Betrachten wir ein weiteres Beispiel, in dem wir einige Informationen eines Buches mit Titel und Sprache als Primärschlüsselfeldern beibehalten müssen.
In diesem Fall muss die Primärschlüsselklasse BookID mit @Embeddable:
@Embeddablepublic class BookId implements Serializable { private String title; private String language; // default constructor public BookId(String title, String language) { this.title = title; this.language = language; } // getters, equals() and hashCode() methods}
Dann müssen wir diese Klasse mit @EmbeddedId in die Book-Entität @EmbeddedId:
@Entitypublic class Book { @EmbeddedId private BookId bookId; // constructors, other fields, getters and setters}
@ IdClass vs @EmbeddedId
Wie wir gerade gesehen haben, besteht der Unterschied zwischen diesen beiden darin, dass wir mit @IdClass die Spalten zweimal angeben mussten – einmal in AccountId und erneut in Account. Aber mit @EmbeddedId haben wir das nicht getan.
Es gibt jedoch einige andere Kompromisse.
Diese unterschiedlichen Strukturen wirken sich beispielsweise auf die JPQL-Abfragen aus, die wir schreiben.
Mit @IdClass ist die Abfrage beispielsweise etwas einfacher:
SELECT account.accountNumber FROM Account account
Mit @EmbeddedId müssen wir eine zusätzliche Durchquerung durchführen:
SELECT book.bookId.title FROM Book book
Außerdem kann @IdClass an Orten sehr nützlich sein, an denen wir eine zusammengesetzte Schlüsselklasse verwenden, die wir nicht ändern können.
Wenn wir auf Teile des zusammengesetzten Schlüssels einzeln zugreifen möchten, können wir @IdClass verwenden, aber an Orten, an denen wir häufig den vollständigen Bezeichner als Objekt verwenden, wird @EmbeddedId bevorzugt.
Fazit
In diesem kurzen Artikel untersuchen wir zusammengesetzte Primärschlüssel in JPA.
Wie immer kann der vollständige Code für diesen Artikel auf Github gefunden werden.