5.1 Diverses formes de communication en tête-à-tête
Il existe un autre cas intéressant et plutôt spécifique de relation entre deux classes Entity - une relation un-à-un.
J'appelle ce cas très spécifique, car il s'agit plus d'objets Java que d'une base de données. Dans la base de données, il n'y a que deux options pour la relation entre les tables :
- La ligne de la table contient un lien vers l'ID d'une autre table.
- La table de service est utilisée pour les relations plusieurs-à-plusieurs.
Dans le cas des classes Entity, il peut y avoir des options décrites par plusieurs annotations :
- @Embarqué
- OneToOne unilatéral
- Bilatéral OneToOne
- @MapsId
Ci-dessous, nous examinerons les plus populaires d'entre eux.
5.2 Intégré
Soit dit en passant, nous avons déjà envisagé l' option de communication individuelle@Embedded
la plus simple - il s'agit d'une annotation . Dans ce cas, nous avons deux classes stockées dans la même table de la base de données.
Disons que nous voulons stocker l'adresse de l'utilisateur dans la classe UserAddress :
@Embeddable
class UserAddress {
@Column(name="user_address_country")
public String country;
@Column(name="user_address_city")
public String city;
@Column(name="user_address_street")
public String street;
@Column(name="user_address_home")
public String home;
}
Il suffit ensuite d'ajouter un champ avec cette adresse à la classe User :
@Entity
@Table(name="user")
class User {
@Column(name="id")
public Integer id;
@Embedded
public UserAddress address;
@Column(name="created_date")
public Date createdDate;
}
Hibernate fera le reste : les données seront stockées dans une seule table, mais lors de l'écriture de requêtes HQL, vous devrez opérer sur des champs de classe.
Exemple de requête HQL :
select from User where address.city = 'Paris'
5.3 OneToOne unilatéral
Imaginez maintenant la situation : nous avons une table source employee et une tâche qui fait référence à employee. Mais nous savons avec certitude qu'un maximum d'une tâche peut être assigné à un utilisateur. Ensuite, nous pouvons utiliser l'annotation pour décrire cette situation @OneToOne
.
Exemple:
@Entity
@Table(name="task")
class EmployeeTask {
@Column(name="id")
public Integer id;
@Column(name="name")
public String description;
@OneToOne
@JoinColumn(name = "employee_id")
public Employee employee;
@Column(name="deadline")
public Date deadline;
}
Hibernate s'assurera que non seulement une tâche a un utilisateur, mais aussi qu'un utilisateur n'a qu'une seule tâche. Sinon, ce cas n'est pratiquement pas différent de @ManyToOne
.
5.4 Bilatéral OneToOne
L'option précédente peut être un peu gênante, car souvent vous souhaitez affecter un employé non seulement à une tâche, mais également affecter une tâche à un employé.
Pour ce faire, vous pouvez ajouter le champ EmployeeTask à la classe Employee et lui donner les annotations correctes.
@Entity
@Table(name="employee")
class Employee {
@Column(name="id")
public Integer id;
@OneToOne(cascade = CascadeType.ALL, mappedBy="employee")
private EmployeeTask task;
}
Important!La table des employés n'a pas de champ task_id , à la place le champ employee_id de la table des tâches est utilisé pour établir une relation entre les tables .
L'établissement d'une connexion entre des objets ressemble à ceci :
Employee director = session.find(Employee.class, 4);
EmployeeTask task = session.find(EmployeeTask.class, 101);
task.employee = director;
director.task = task;
session.update(task);
session.flush();
Pour supprimer le lien, les liens doivent également être supprimés des deux objets :
Employee director = session.find(Employee.class, 4);
EmployeeTask task = director.task;
task.employee = null;
session.update(task);
director.task = null;
session.update(director);
session.flush();
GO TO FULL VERSION