154 votes

Qu'est-ce que le "côté propriétaire" dans un mappage ORM ?

Que fait exactement le côté propriétaire C'est-à-dire ? Quelle est une explication avec quelques exemples de cartographie ( un à plusieurs, un à un, plusieurs à un ) ?

Le texte suivant est un extrait de la description de @OneToOne dans la documentation de Java EE 6. Vous pouvez voir le concept côté propriétaire en elle.

Définit une association à valeur unique avec une autre entité qui a une relation multiplicité. Il n'est normalement pas nécessaire de spécifier l'entité associée explicitement l'entité cible associée, car elle peut généralement être déduite du type de l'objet l'objet référencé. Si la relation est bidirectionnelle, la relation le site côté non-propriétaire doit utiliser l'option mappedBy de l'annotation OneToOne pour spécifier le champ de relation ou la propriété du côté propriétaire.

1 votes

10 votes

J'étais perdue jusqu'à ce que je lise ceci : javacodegeeks.com/2013/04/

5 votes

La table de la BD avec la colonne de la clé étrangère est traitée comme le côté propriétaire. Ainsi, l'entité commerciale représentant cette table de base de données est le propriétaire (côté propriétaire) de cette relation. Pas nécessairement, mais dans la plupart des cas, le côté propriétaire aura l'annotation @JoinColumn.

248voto

jhadesdev Points 10717

Pourquoi la notion d'un 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 - les clés étrangères.

Quelle est la raison de l'appellation "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 la notion de côté propriétaire résout ?

Prenons l'exemple de deux entités mises en correspondance sans déclarer un 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 mappage définit non pas une relation bidirectionnelle, mais deux des relations unidirectionnelles distinctes.

La cartographie créerait non seulement des tables PERSONS y 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)
)

Remarquez 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 .

D'autre part, si nous appelons idDocument.setPerson(person) nous changeons la clé étrangère person_id sur la table ID_DOCUMENTS . Hibernate crée deux des relations unidirectionnelles (clés étrangères) sur la base de données, pour mettre en œuvre les éléments suivants un relation d'objet bidirectionnelle.

Comment la notion de propriété d'un côté résout le problème :

Souvent, ce que nous voulons est seulement une clé étrangère sur la table ID_DOCUMENTS vers PERSONS et non la table d'association supplémentaire.

Pour résoudre ce problème, nous devons configurer Hibernate pour qu'il cesse de suivre les modifications de la relation. Person.idDocuments . Hibernate ne devrait suivre que les 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à Cartographié par l'autre côté de la relation IdDocument.person, donc pas besoin de de le suivre ici séparément dans une table supplémentaire."

Y a-t-il des GOTCHAs, des conséquences ?

Utilisation de mappedBy Si on appelle seulement person.getDocuments().add(document) la clé étrangère dans ID_DOCUMENTS sera PAS être lié 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 explicitement appeler document.setPerson(person) parce que c'est la côté propriétaire de la relation.

Lorsque vous utilisez mappedBy Dans ce cas, il incombe au développeur de savoir quel est le côté propriétaire, et de mettre à jour le côté correct de la relation afin de déclencher la persistance de la nouvelle relation dans la base de données.

22 votes

La meilleure réponse que j'ai trouvée qui explique la doctrine 'mappedBy' + 'inversedBy'.

1 votes

Merci d'avoir précisé les mappings et la raison d'être du concept.

2 votes

Je ne sais pas si les choses ont changé, mais sous Hibernate 5.0.9.Final si je " n'appelle que person.getDocuments().add(document) , " hibernate met à jour la clé étrangère en ID_DOCUMENTS .

149voto

Jack Points 61503

Vous pouvez imaginer que le côté propriétaire est l'entité qui a la référence à l'autre. Dans votre extrait, vous avez une relation biunivoque. Puisque c'est une symétrique vous finirez par avoir que si l'objet A est en relation avec l'objet B alors le vice-versa est également vrai.

Cela signifie que l'enregistrement dans l'objet A d'une référence à l'objet B et l'enregistrement dans l'objet B d'une référence à l'objet A seront redondants : c'est pourquoi vous choisissez quel objet "possède" l'autre ayant la référence à lui.

Lorsque vous avez une relation de type "one-to-many", les objets liés à la partie "many" seront les propriétaires, sinon vous devrez stocker de nombreuses références d'un seul objet à une multitude. Pour éviter cela, chaque objet de la deuxième classe aura un pointeur vers l'objet unique auquel il se réfère (il est donc le propriétaire).

Pour une relation many-to-many, comme vous aurez de toute façon besoin d'une table de correspondance séparée, il n'y aura pas de côté propriétaire.

En conclusion, le côté propriétaire est l'entité qui a la référence à l'autre.

6 votes

Merci de votre précision.

2 votes

Vous pouvez également consulter ci-dessous ma réponse sur les raisons des noms "mappedBy" et "owning side", ce qui se passe si nous ne définissons pas de "owning side", GOTCHAs, j'espère que cela vous aidera.

6 votes

Eh bien, la réponse est en grande partie correcte, je suppose. Mais pour Hibernate au moins, même les relations many-to-many ont un côté propriétaire. Cela a des conséquences sur le comportement de mise à jour, par exemple. Regardez attentivement la section 4 ("Update Hibernate Model Class") de ce tutoriel : viralpatel.net/blogs/

2voto

debugmode Points 123

Je vais vous donner une explication très brève à ce sujet. "Owning" signifie qu'il porte la colonne de la clé étrangère en lui-même. En d'autres termes, elle possède la relation. Beaucoup de gens comprennent mal le mot "propriétaire". Ils pensent que la partie propriétaire est la partie principale. Mais quand on y regarde de plus près, la table avec la colonne de clé étrangère est la partie liée. Par exemple : Pensons à Personne et Adresse et à la relation entre eux OneToOne

@Data
@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne
    @JoinColumn(name = "adress_id")
    private Adress adress;
}

@Data
@Entity
public class Adress {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "adress")
    private Person person;

}

Dans ce cas, la personne a la colonne fk adress_id qui est liée à l'adresse de la colonne clé primaire.

0voto

Vishnu Shinde Points 1

Les relations bidirectionnelles doivent respecter ces règles.

Le côté inverse d'une relation bidirectionnelle doit faire référence à son côté propriétaire en utilisant l'élément mappedBy de l'annotation @OneToOne, @OneToMany ou @ManyToMany. L'élément mappedBy désigne la propriété ou le champ de l'entité qui est le propriétaire de la relation.

Le côté many des relations bidirectionnelles many-to-one ne doit pas définir l'élément mappedBy. Le côté multiple est toujours le côté propriétaire de la relation. (Selon les documents d'Oracle : https://docs.oracle.com/cd/E19798-01/821-1841/bnbqi/index.html )

Pour les relations bidirectionnelles biunivoques, le côté propriétaire correspond au côté qui contient la clé étrangère correspondante.

Pour les relations bidirectionnelles entre plusieurs personnes, l'un ou l'autre côté peut être le côté propriétaire.

0voto

Eh bien, ça aide beaucoup. Je vote en faveur de cette discussion

Je recherchais en particulier le cas d'utilisation suivant dans le système de gestion des hôpitaux. Patient->Historique du patient Le patient n'est pas dépendant de l'historique du patient, c'est-à-dire qu'il faut ajouter l'historique de sa maladie uniquement lors de sa première visite à l'hôpital. 2. Lors des visites suivantes, l'historique est ajouté dans la table d'historique, mais il faut une référence patient_id au patient. Donc ici, comme la clé étrangère est dans la table PatientHIstory, le côté propriétaire est PatientHistory.

Cette relation doit donc être modélisée de manière bidirectionnelle OneToMany, mappedby="patient" dans l'entité patient. Chacune des entités se réfère à une autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X