Eins-zu-Eins-Beziehung in JPA

Eins-zu-eins-Beziehung in JPA

1. Einführung

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 unserenGuide to Hibernate 5 with Spring.

Weitere Lektüre:

Übersicht über JPA / Hibernate-Kaskadentypen

Ein schneller und praktischer Überblick über JPA / Hibernate Cascade Types.

Read more

Hibernate One to Many Annotation Tutorial

In diesem Tutorial sehen wir uns die Eins-zu-Viele-Zuordnung mithilfe von JPA-Anmerkungen anhand eines praktischen Beispiels an.

Read more

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 zwischenuser undaddress entitäten.

Lassen Sie uns in den folgenden Abschnitten sehen, wie wir dies implementieren können.

3. Verwenden eines Fremdschlüssels

3.1. Modellierung mit einem Fremdschlüssel

Schauen wir uns die folgendenER diagraman, die eine Fremdschlüssel-basierte Eins-zu-Eins-Zuordnung darstellen:

An ER Diagram mapping Users to Addresses via an address_id foreign key

In diesem Beispiel ist dieaddress_id -Spalte inusers dieforeign key bisaddress.

3.2. Implementieren mit einem Fremdschlüssel in JPA

Erstellen wir zunächst dieUser -Skala und kommentieren Sie sie entsprechend:

@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, dasswe place the @OneToOne annotation im zugehörigen EntitätsfeldAddress ist.

Außerdemwe need to place the @JoinColumn annotation, um den Namen der Spalte in der Tabelleuserszu konfigurieren, die dem Primärschlüssel in der Tabelleaddress zugeordnet ist. Wenn wir keinen Namen angeben, wählt Hibernatefollow some rules aus, um einen Standardnamen auszuwählen.

Beachten Sie schließlich in der nächsten Entität, dass wir dort nicht die@JoinColumn -Sannotation verwenden. Dies liegt daran, dass wir es nur auf derowning -Seite der Fremdschlüsselbeziehung benötigen. Simply put, whoever owns the foreign key column gets the @JoinColumn annotation.

DieAddress -Sentitä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
}

Auch hier müssen wir die@OneToOne -Sannotation platzieren. Dies liegt daran, dass dies einbidirectional relationshipist. The address side of the relationship is called the non-owning side. 

4. Verwenden eines freigegebenen Primärschlüssels

4.1. Modellierung mit einem gemeinsamen Primärschlüssel

In dieser Strategie wird anstelle einer neuen Spalteaddress_id, we’ll mark the primary key column (user_id) of the address table as the foreign key to the users table erstellt:

An ER diagram with Users Tied to Addresses where they share the same primary key values

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. Implementieren mit einem freigegebenen 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)
    private Address address;

    //... getters and setters
}
@Entity
@Table(name = "address")
public class Address {

    @Id
    @Column(name = "id")
    private Long id;

    //...

    @OneToOne
    @MapsId
    private User user;

    //... getters and setters
}

@MapsId tells Hibernate to use the id column of address as both primary key and foreign key. Beachten Sie auch, dassthe @Id column of the Address entity no longer uses the @GeneratedValue annotation.

Das AttributmappedBy wird jetzt in die KlasseUser verschoben, da der Fremdschlüssel jetzt im Stalladdress vorhanden ist.

5. Join-Tabelle verwenden

Es gibt zwei Arten von Eins-zu-Eins-Zuordnungen:Optional undMandatory. So far, we’ve seen only mandatory relationships.

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

5.1. Modellierung mit einer Join-Tabelle

Die Strategien, die wir diskutiert haben until now force us to put null values in the column to handle optional relationships.

Normalerweise denken wir anmany-to-many relationships, wenn wir eine Verknüpfungstabellebut, using a join table, in this case, can help us to eliminate these null values: betrachten

An ER diagram relating Employees to Workstations via a Join Table

Wenn wir nun eine Beziehung haben, werden wir einen Eintrag imemp_workstation -Stabil vornehmen und Nullen insgesamt vermeiden.

5.2. Implementierung mit einer Join-Tabelle in JPA

Unser erstes Beispiel verwendet@JoinColumn.  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-Table-Strategie anzuwenden, während die Beziehung beibehalten wird.

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

6. Fazit

In diesem Lernprogramm haben wir verschiedene Methoden zum Verwalten einer Eins-zu-Eins-Zuordnung in JPA und Hibernate kennengelernt.

Der Quellcode dieses Tutorials befindet sich inover on GitHub.