Dans la séance précédente, nous avons vu en détail les mappings uni-directionnels.
Dans cette séance, nous allons voir brièvement le cas des mappings bi-directionnels.
Il y a un mapping bi-directionnel si les objets de A contiennent des objets de B ET que les objets de B contiennent des objets de A correspondants.
public class Student { public class Student { private long id; private String firstName; private String lastName; private Set<PhoneNumber> phoneNumbers; ... } public class PhoneNumber { private long id; private String phoneNumber; private Student owner; ... }
Dans Student
, phoneNumbers
est un @OneToMany
.
Symétriquement, dans PhoneNumber
, student
est un @ManyToOne
.
En BD, cette relation n'est représentée qu'une seule fois. En JPA, un seul des cotés est responsable/propriétaire
de la relation. C'est toujours le @ManyToOne
. Le côté qui n'est pas responsable doit faire référence au coté responsable avec l'annotation mappedBy
.
Pour une @ManyToMany
, il faut choisir un coté comme responsable.
@Entity public class Student { @Id @GeneratedValue private long id; private String firstName; private String lastName; @OneToMany(cascade = CascadeType.ALL,mappedBy="owner") private Set<PhoneNumber> phoneNumbers; }
@Entity public class PhoneNumber { @Id @GeneratedValue private long id; private String phoneNumber; @ManyToOne(fetch = FetchType.LAZY) private Student owner; }
mappedBy="owner"
indique que la relation
@OneToMany
est en fait un reflet de la relation @ManyToOne
sur le champ owner
de PhoneNumber
.
PhoneNumber
, on ne veut pas supprimer le Student
.FetchType
de la relation ManyToOne
car il est EAGER
par défaut.Prenons un Student student
et un PhoneNumber phoneNumber
.
Si phoneNumber
appartient à student.phoneNumbers
alors il faut que student
==
phoneNumber.student
.
Il n'y a pas de magie, c'est à votre code de maintenir cette contrainte. JPA ne le fera pas pour vous automatiquement. Si vous enlever un PhoneNumber
de student.phoneNumbers
, il faut mettre le champ PhoneNumber.student
à null
.
La norme JPA indique que si la correspondance entre les objets n'est pas maintenue correctement, le mapping vers la BD peut ne pas être correct.
public Student(String firstName, String lastName,Address address,Set<PhoneNumber> phoneNumbers,University university) { this.firstName = firstName; this.lastName = lastName; this.phoneNumbers= new HashSet<>(); for (PhoneNumber phoneNumber : phoneNumbers) { addPhoneNumber(phoneNumber); } this.address = address; this.university = university; } public void addPhoneNumber(PhoneNumber phoneNumber){ phoneNumbers.add(phoneNumber); phoneNumber.setStudent(this); } public void removePhoneNumber(PhoneNumber phoneNumber){ phoneNumbers.remove(phoneNumber); phoneNumber.setStudent(null); }