Relation un à un dans JPA
1. introduction
Dans ce didacticiel, nous allons examiner différentes manières de créer des mappages un-à-un dans JPA.
Nous aurons besoin d'une compréhension de base du framework Hibernate, veuillez donc consulter nosGuide to Hibernate 5 with Spring pour plus d'informations.
Lectures complémentaires:
Présentation des types JPA / Hibernate Cascade
Un aperçu rapide et pratique des types de cascade JPA / Hibernate.
Tutoriel Annotation Hibernate Un à Plusieurs
Dans ce didacticiel, nous allons examiner le mappage un-à-plusieurs à l'aide d'annotations JPA avec un exemple pratique.
2. La description
Supposons que nous construisions un système de gestion des utilisateurs et que notre patron nous demande de stocker une adresse postale pour chaque utilisateur. Un utilisateur aura une adresse postale et une adresse postale ne sera associée qu’à un seul utilisateur.
Voici un exemple de relation biunivoque, dans ce cas entreuser andaddress entities.
Voyons comment nous pouvons mettre cela en œuvre dans les sections suivantes.
3. Utiliser une clé étrangère
3.1. Modélisation avec une clé étrangère
Examinons lesER diagram suivants, qui représentent un mappage un-à-un basé sur une clé étrangère:
Dans cet exemple, la scolumnaddress_id dansusers est laforeign key àaddress.
3.2. Mise en œuvre avec une clé étrangère dans JPA
Commençons par créer la classeUser et annotons-la de manière appropriée:
@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
}
Notez quewe place the @OneToOne annotation sur le champ d'entité associé,Address.
De plus,we need to place the @JoinColumn annotation pour configurer le nom de la colonne dans la tableusers qui correspond à la clé primaire dans la tableaddress. Si nous ne fournissons pas de nom, Hibernate ferafollow some rules pour en sélectionner un par défaut.
Enfin, notez dans l'entité suivante que nous n'utiliserons pas l'annotation@JoinColumn ici. C'est parce que nous n'en avons besoin que du côtéowning de la relation de clé étrangère. Simply put, whoever owns the foreign key column gets the @JoinColumn annotation.
La sentitéAddress 'avère un peu plus simple:
@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
}
Nous devons également placer ici la sannotation@OneToOne . C’est parce qu’il s’agit d’unbidirectional relationship. The address side of the relationship is called the non-owning side.
4. Utilisation d'une clé primaire partagée
4.1. Modélisation avec une clé primaire partagée
Dans cette stratégie, au lieu de créer une nouvelle colonneaddress_id, we’ll mark the primary key column (user_id) of the address table as the foreign key to the users table:
Nous avons optimisé l'espace de stockage en utilisant le fait que ces entités ont une relation un à un entre elles.
4.2. Mise en œuvre avec une clé primaire partagée dans JPA
Notez que nos définitions ne changent que légèrement:
@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. Notez également quethe @Id column of the Address entity no longer uses the @GeneratedValue annotation.
L'attributmappedBy est maintenant déplacé vers la classeUser car la clé étrangère est maintenant présente dans le stableaddress .
5. Utiliser une table de jointure
Les mappages un-à-un peuvent être de deux types -Optional etMandatory. So far, we’ve seen only mandatory relationships.
Maintenant, imaginons que nos employés soient associés à un poste de travail. C'est un à un, mais parfois un employé peut ne pas avoir de poste de travail et vice-versa.
5.1. Modélisation avec une table de jointure
Les stratégies dont nous avons discuté until now force us to put null values in the column to handle optional relationships.
Typiquement, nous pensons àmany-to-many relationships lorsque nous considérons une table de jointure,but, using a join table, in this case, can help us to eliminate these null values:
Maintenant, chaque fois que nous avons une relation, nous allons faire une entrée dans leemp_workstation table et éviter les nulls altogether.
5.2. Mise en œuvre avec une table de jointure dans JPA
Notre premier exemple utilise@JoinColumn. Cette fois, nous utiliserons@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 indique à Hibernate d'utiliser la stratégie de table de jointure tout en maintenant la relation.
De plus,Employee est le propriétaire de cette relation car nous avons choisi d'y utiliser l'annotation de table de jointure.
6. Conclusion
Dans ce didacticiel, nous avons appris différentes manières de maintenir une association un-à-un dans JPA et Hibernate et à utiliser chacune d'elles.
Le code source de ce tutoriel peut être trouvéover on GitHub.