Eins-zu-eins-Beziehung in JPA

1. Einleitung

In diesem Tutorial werden verschiedene Möglichkeiten zum Erstellen von Eins-zu-Eins-Zuordnungen in JPA vorgestellt.

Wir benötigen ein grundlegendes Verständnis des Hibernate-Frameworks. Weitere Hintergrundinformationen finden Sie in unserem Handbuch zu Hibernate 5 mit Spring.

2. Beschreibung

Nehmen wir an, wir bauen ein Benutzerverwaltungssystem auf und unser Chef fordert uns auf, für jeden Benutzer eine Postanschrift zu speichern. Ein Benutzer hat eine Postanschrift, und an eine Postanschrift ist nur ein Benutzer gebunden.

Dies ist ein Beispiel für eine Eins-zu-Eins-Beziehung, in diesem Fall zwischen Benutzer- und Adressentitäten .

Mal sehen, wie wir dies in den folgenden Abschnitten implementieren können.

3. Verwenden eines Fremdschlüssels

3.1. Modellieren mit einem Fremdschlüssel

Schauen wir uns das folgende ER-Diagramm an, das eine Fremdschlüssel-basierte Eins-zu-Eins-Zuordnung darstellt:

In diesem Beispiel ist die Spalte address_id in Benutzern der zu adressierende Fremdschlüssel .

3.2. Implementierung mit einem Fremdschlüssel in JPA

Lassen Sie uns zunächst die Benutzerklasse erstellen und entsprechend kommentieren:

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; //... @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "address_id", referencedColumnName = "id") private Address address; // ... getters and setters } 

Beachten Sie, dass wir die Annotation @OneToOne in das zugehörige Entitätsfeld Adresse einfügen .

Außerdem müssen wir die platzieren @JoinColumn Annotation die Namen der Spalte in der konfigurieren Benutzer - Tabelle , die in der auf den Primärschlüssel abbildet Adresse Tabelle. Wenn wir keinen Namen angeben, befolgt der Ruhezustand einige Regeln, um einen Standardnamen auszuwählen.

Beachten Sie schließlich in der nächsten Entität, dass wir dort die Annotation @JoinColumn nicht verwenden . Dies liegt daran, dass wir es nur auf der Besitzerseite der Fremdschlüsselbeziehung benötigen . Einfach ausgedrückt, wer die Fremdschlüsselspalte besitzt, erhält die Annotation @JoinColumn .

Die Adressentität fällt etwas einfacher aus:

@Entity @Table(name = "address") public class Address { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; //... @OneToOne(mappedBy = "address") private User user; //... getters and setters }

Wir müssen auch hier die Annotation @OneToOne platzieren . Das liegt daran, dass dies eine bidirektionale Beziehung ist. Die Adressseite der Beziehung wird als nicht besitzende Seite bezeichnet.

4. Verwenden eines freigegebenen Primärschlüssels

4.1. Modellierung mit einem gemeinsamen Primärschlüssel

In dieser Strategie markieren wir anstelle einer neuen Spalte address_id den PrimärschlüsselSpalte (User_id) der Adressentabelle als Fremdschlüssel für die Benutzer - Tabelle :

Wir haben den Speicherplatz optimiert, indem wir die Tatsache genutzt haben, dass diese Entitäten eine Eins-zu-Eins-Beziehung zwischen ihnen haben.

4.2. Implementierung mit einem gemeinsam genutzten Primärschlüssel in JPA

Beachten Sie, dass sich unsere Definitionen nur geringfügig ändern:

@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; //... @OneToOne(mappedBy = "user", cascade = CascadeType.ALL) @PrimaryKeyJoinColumn private Address address; //... getters and setters }
@Entity @Table(name = "address") public class Address { @Id @Column(name = "user_id") private Long id; //... @OneToOne @MapsId @JoinColumn(name = "user_id") private User user; //... getters and setters } 

Das mappedBy Attribut wird nun auf die bewegte Benutzerklasse , da die Fremdschlüssel nun in der ist Adresstabelle. Wir haben auch hinzugefügt , die @PrimaryKeyJoinColumn Anmerkung, was darauf hindeutet , dass der Primärschlüssel der Benutzereinheit als Fremdschlüsselwert für die zugehörige verwendete Adresse Entität .

Wir haben immer noch eine definieren @Id Feld in der Adressklasse , aber diese Referenzen die Notiz user_id Spalte, und es nicht mehr verwendet die @GeneratedValue Anmerkung. Auch auf dem Gebiet , dass Verweise der Benutzer , haben wir hinzugefügt , die @MapsId Anmerkung, was darauf hindeutet , dass die Primärschlüsselwerte kopiert werden von der Benutzereinheit.

5. Verwenden einer Join-Tabelle

Es gibt zwei Arten von Eins-zu-Eins-Zuordnungen: Optional und Obligatorisch . Bisher haben wir nur obligatorische Beziehungen gesehen.

Stellen wir uns nun vor, unsere Mitarbeiter werden mit einer Workstation verbunden. Es ist eins zu eins, aber manchmal hat ein Mitarbeiter keine Workstation und umgekehrt.

5.1. Modellierung mit einer Join-Tabelle

Die Strategien, die wir bisher besprochen haben, zwingen uns, Nullwerte in die Spalte einzufügen, um optionale Beziehungen zu behandeln .

Normalerweise denken wir an viele-zu-viele-Beziehungen, wenn wir eine Join-Tabelle betrachten. In diesem Fall kann uns die Verwendung einer Join-Tabelle jedoch dabei helfen, diese Nullwerte zu beseitigen:

Wenn wir jetzt eine Beziehung haben, machen wir einen Eintrag in der Tabelle emp_workstation und vermeiden Nulleninsgesamt.

5.2. Implementierung mit einer Join-Tabelle in JPA

In unserem ersten Beispiel wurde @JoinColumn verwendet. Dieses Mal verwenden wir @JoinTable :

@Entity @Table(name = "employee") public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; //... @OneToOne(cascade = CascadeType.ALL) @JoinTable(name = "emp_workstation", joinColumns = { @JoinColumn(name = "employee_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "workstation_id", referencedColumnName = "id") }) private WorkStation workStation; //... getters and setters }
@Entity @Table(name = "workstation") public class WorkStation { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; //... @OneToOne(mappedBy = "workStation") private Employee employee; //... getters and setters }

@ JoinTable weist Hibernate an, die Join-Tabellen-Strategie anzuwenden , während die Beziehung beibehalten wird.

Außerdem ist der Mitarbeiter der Eigentümer dieser Beziehung, da wir die Annotation der Verknüpfungstabelle verwendet haben.

6. Fazit

In diesem Tutorial haben wir verschiedene Methoden kennengelernt, um eine Eins-zu-Eins-Zuordnung in JPA und Hibernate aufrechtzuerhalten und wann sie verwendet werden müssen.

Den Quellcode dieses Tutorials finden Sie auf GitHub.