Een-op-een-relatie in JPA

1. Inleiding

In deze zelfstudie bekijken we verschillende manieren om een-op-een-toewijzingen in JPA te maken.

We hebben basiskennis van het Hibernate-framework nodig, dus bekijk onze Guide to Hibernate 5 with Spring voor extra achtergrondinformatie.

2. Beschrijving

Stel dat we een gebruikersbeheersysteem aan het bouwen zijn en dat onze baas ons vraagt ​​om voor elke gebruiker een postadres op te slaan. Een gebruiker heeft één postadres en aan een postadres is slechts één gebruiker gekoppeld.

Dit is een voorbeeld van een één-op-één-relatie, in dit geval tussen gebruiker en adres entiteiten.

Laten we eens kijken hoe we dit in de volgende secties kunnen implementeren.

3. Een externe sleutel gebruiken

3.1. Modelleren met een externe sleutel

Laten we eens kijken naar het volgende ER-diagram dat een op een externe sleutel gebaseerde een-op-een-toewijzing vertegenwoordigt:

In dit voorbeeld is de address_id kolom in gebruikers is de externe sleutel naar adres.

3.2. Implementeren met een externe sleutel in JPA

Laten we eerst het Gebruiker class en annoteer het op de juiste manier:

@Entity @Table (naam = "gebruikers") openbare klasse Gebruiker {@Id @GeneratedValue (strategie = GenerationType.AUTO) @Column (naam = "id") privé Lange id; // ... @OneToOne (cascade = CascadeType.ALL) @JoinColumn (naam = "address_id", referencedColumnName = "id") privéadres; // ... getters en setters} 

Let daar op we plaatsen de @Een op een annotatie op het gerelateerde entiteitsveld, Adres.

Ook, we moeten de @JoinColumn annotatie om de naam van de kolom in het gebruikers tabel die is toegewezen aan de primaire sleutel in het adres tafel. Als we geen naam opgeven, volgt Hibernate enkele regels om een ​​standaardnaam te selecteren.

Merk ten slotte op in de volgende entiteit dat we de @JoinColumn aantekening daar. Dit komt omdat we het alleen nodig hebben op de bezitten kant van de relatie met de externe sleutel. Simpel gezegd, wie dan ook bezit de kolom met de externe sleutel krijgt de @JoinColumn annotatie.

De Adres entiteit blijkt een beetje eenvoudiger:

@Entity @Table (naam = "adres") openbare klasse Adres {@Id @GeneratedValue (strategie = GenerationType.AUTO) @Column (naam = "id") privé Lange id; // ... @OneToOne (mappedBy = "address") privégebruiker; // ... getters en setters}

We moeten ook het @Een op een annotatie hier ook. Dat komt omdat dit een bidirectionele relatie is. De adreszijde van de relatie wordt de niet-bezit kant.

4. Met behulp van een gedeelde primaire sleutel

4.1. Modelleren met een gedeelde primaire sleutel

In deze strategie, in plaats van een nieuwe kolom te maken address_id, we zullen de primaire sleutel markerenkolom (gebruikersnaam) van de adreslijst als de externe sleutel voor het gebruikers tafel:

We hebben de opslagruimte geoptimaliseerd door gebruik te maken van het feit dat deze entiteiten onderling een één-op-één-relatie hebben.

4.2. Implementeren met een gedeelde primaire sleutel in JPA

Merk op dat onze definities slechts in geringe mate veranderen:

@Entity @Table (naam = "gebruikers") openbare klasse Gebruiker {@Id @GeneratedValue (strategie = GenerationType.AUTO) @Column (naam = "id") privé Lange id; // ... @OneToOne (mappedBy = "user", cascade = CascadeType.ALL) @PrimaryKeyJoinColumn privé-adresadres; // ... getters en setters}
@Entity @Table (name = "address") openbare klasse Adres {@Id @Column (name = "user_id") privé Lange id; // ... @OneToOne @MapsId @JoinColumn (name = "user_id") privégebruiker; // ... getters en setters} 

De mappedBy attribuut is nu verplaatst naar het Gebruiker class aangezien de externe sleutel nu aanwezig is in de adres tafel. We hebben ook toegevoegd de @BuienRadarNL annotatie, die aangeeft dat de primaire sleutel van het Gebruiker entiteit wordt gebruikt als de waarde van de externe sleutel voor het gekoppelde Adres entiteit.

We moeten nog een @ID kaart veld in het Adres class maar merk op dat dit verwijst naar de gebruikersnaam kolom, en het gebruikt niet langer de @GeneratedValue annotatie. Ook op het veld dat verwijst naar het Gebruiker, hebben we toegevoegd de @MapsId annotatie, die aangeeft dat de primaire sleutelwaarden worden gekopieerd van de Gebruiker entiteit.

5. Met behulp van een samenvoegtafel

Een-op-een-toewijzingen kunnen van twee typen zijn: Optioneel en Verplicht. Tot nu toe hebben we alleen verplichte relaties gezien.

Laten we nu eens kijken hoe onze medewerkers geassocieerd worden met een werkplek. Het is een-op-een, maar soms heeft een werknemer geen werkplek en vice versa.

5.1. Modelleren met een meettafel

De strategieën die we hebben besproken dwingen ons tot nu toe om null-waarden in de kolom te plaatsen om optionele relaties af te handelen.

Meestal denken we aan veel-op-veel-relaties als we een samenvoegtafel overwegen, maar in dit geval kan het gebruik van een join-tabel ons helpen deze null-waarden te elimineren:

Nu, telkens als we een relatie hebben, zullen we een vermelding in de emp_workstation tabel en vermijd null-waardenallemaal samen.

5.2. Implementeren met een Join Table in JPA

Ons eerste voorbeeld is gebruikt @JoinColumn. Deze keer gebruiken we @JoinTable:

@Entity @Table (naam = "werknemer") openbare klasse Werknemer {@Id @GeneratedValue (strategie = GenerationType.AUTO) @Column (naam = "id") privé Lange id; // ... @OneToOne (cascade = CascadeType.ALL) @JoinTable (name = "emp_workstation", joinColumns = {@JoinColumn (name = "employee_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn (naam = "workstation_id", referencedColumnName = "id")}) privé WorkStation-werkstation; // ... getters en setters}
@Entity @Table (naam = "werkstation") openbare klasse WorkStation {@Id @GeneratedValue (strategie = GenerationType.AUTO) @Column (naam = "id") privé Lange id; // ... @OneToOne (mappedBy = "workStation") privé werknemer werknemer; // ... getters en setters}

@JoinTable instrueert Hibernate om de join-tafelstrategie toe te passen terwijl de relatie wordt gehandhaafd.

Ook, Werknemer is de eigenaar van deze relatie omdat we ervoor hebben gekozen om de aantekening van de join-tafel erop te gebruiken.

6. Conclusie

In deze zelfstudie hebben we verschillende manieren geleerd om een ​​één-op-één-koppeling in JPA en Hibernate te behouden en wanneer we ze allemaal moeten gebruiken.

De broncode van deze tutorial is te vinden op GitHub.