Pourquoi la notion de côté propriétaire est-elle nécessaire:
L'idée d'un côté propriétaire d'une relation bidirectionnelle vient du fait que dans les bases de données relationnelles, il n'y a pas de relations bidirectionnelles comme dans le cas des objets. Dans les bases de données, nous n'avons que des relations unidirectionnelles - des clés étrangères.
Quelle est la raison du nom «côté propriétaire»?
Le côté propriétaire de la relation suivie par Hibernate est le côté de la relation qui possède la clé étrangère dans la base de données.
Quel est le problème que résout la notion de côté propriétaire?
Prenons un exemple de deux entités mappées sans déclarer de côté propriétaire:
@Entity
@Table(name="PERSONS")
public class Person {
@OneToMany
private List<IdDocument> idDocuments;
}
@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
@ManyToOne
private Person person;
}
D'un point de vue OO, ce mapping définit non pas une relation bidirectionnelle, mais deux relations unidirectionnelles distinctes.
Le mappage créerait non seulement des tables PERSONS
et ID_DOCUMENTS
, mais créerait également une troisième table d'association PERSONS_ID_DOCUMENTS
:
CREATE TABLE PERSONS_ID_DOCUMENTS
(
persons_id bigint NOT NULL,
id_documents_id bigint NOT NULL,
CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
CONSTRAINT pk UNIQUE (id_documents_id)
)
Notez la clé primaire pk
sur ID_DOCUMENTS
seulement. Dans ce cas, Hibernate suit les deux côtés de la relation indépendamment: Si vous ajoutez un document à la relation Person.idDocuments
, il insère un enregistrement dans la table d'association PERSON_ID_DOCUMENTS
.
Par contre, si nous appelons idDocument.setPerson(person)
, nous changeons la clé étrangère person_id sur la table ID_DOCUMENTS
. Hibernate crée deux relations unidirectionnelles (clé étrangère) sur la base de données, pour implémenter une relation d'objet bidirectionnelle.
Comment la notion de côté propriétaire résout le problème:
Plusieurs fois ce que nous voulons est seulement une clé étrangère sur la table ID_DOCUMENTS
vers PERSONS
et la table d'association supplémentaire.
Pour résoudre ce problème, nous devons configurer Hibernate pour arrêter le suivi des modifications sur la relation Person.idDocuments
. Hibernate ne devrait suivre que l' autre côté de la relation IdDocument.person
, et pour ce faire, nous ajoutons mappedBy :
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
Qu'est-ce que cela signifie mappedBy?
Cela signifie quelque chose comme: "les modifications de ce côté de la relation sont déjà mappées par
l'autre côté de la relation IdDocument.person, donc pas besoin de la suivre ici séparément dans une table supplémentaire."
Y a-t-il des GOTCHA, des conséquences?
En utilisant mappedBy , si nous appelons seulement person.getDocuments().add(document)
, la clé étrangère dans ID_DOCUMENTS
ne sera PAS liée au nouveau document, car ce n'est pas le côté propriétaire / suivi de la relation!
Pour lier le document à la nouvelle personne, vous devez appeler explicitement document.setPerson(person)
, car c'est le côté propriétaire de la relation.
Lors de l'utilisation de mappedBy , il est de la responsabilité du développeur de savoir quel est le côté propriétaire et de mettre à jour le bon côté de la relation afin de déclencher la persistance de la nouvelle relation dans la base de données.