web-dev-qa-db-fra.com

Hibernate / JPA ManyToOne vs OneToMany

Je lis actuellement la documentation d'Hibernate concernant les associations d'entités et je rencontre un peu de difficulté à comprendre certaines choses. Il s'agit essentiellement de la différence entre les associations ManyToOne et OneToMany. Bien que je les ai utilisés dans de vrais projets, je ne peux pas appréhender complètement la différence entre eux. À ma connaissance, si une table/une entité a une association ManyToOne avec une autre, alors l'association devrait être de l'autre côté OneToMany. Alors, comment devrions-nous décider lequel choisir en fonction d'un cas spécifique et comment cela affecte-t-il la base de données/requêtes/résultats? Y a-t-il partout un bon exemple?

P.S .: Je pense qu'il serait utile en raison de sa pertinence pour la question, si quelqu'un pouvait en outre expliquer quel est l'intérêt du propriétaire de l'association et la différence entre l'association bidirectionnelle et l'association unidirectionnelle.

39
arjacsoh

Supposons que vous ayez une commande et une ligne de commande. Vous pouvez choisir d'avoir un OneToMany unidirectionnel entre Order et OrderLine (Order aurait une collection de OrderLines). Ou vous pouvez choisir d'avoir une association ManyToOne entre OrderLine et Order (OrderLine aurait une référence à sa commande). Ou vous pouvez choisir d'avoir les deux, auquel cas l'association devient une association bidirectionnelle OneToMany/ManyToOne.

La solution que vous choisissez dépend principalement de la situation et du niveau de couplage entre les entités. Par exemple, si un utilisateur, une entreprise, un fournisseur ont tous de nombreuses adresses, il serait logique d'avoir une adresse unidirectionnelle entre chacun d'eux et une adresse, et que l'adresse ne connaisse pas leur propriétaire.

Supposons que vous ayez un utilisateur et un message, où un utilisateur peut avoir des milliers de messages, il pourrait être judicieux de le modéliser uniquement en tant que ManyToOne du message à l'utilisateur, car de toute façon, vous demanderez rarement tous les messages d'un utilisateur. L'association ne peut être rendue bidirectionnelle que pour aider aux requêtes, car les requêtes JPQL se joignent entre les entités en naviguant dans leurs associations.

Dans une association bidirectionnelle, vous pourriez être dans une situation où le graphique des objets est incohérent. Par exemple, l'Ordre A aurait un ensemble vide de OrderLines, mais certains OrderLines auraient une référence à l'Ordre A. JPA impose de toujours avoir un côté de l'association étant le côté propriétaire, et l'autre côté étant le côté inverse. Le côté inverse est ignoré par JPA. Le côté propriétaire est le côté qui décide quelle relation existe. Dans une association bidirectionnelle OneToMany, le côté propriétaire doit être le côté plusieurs. Ainsi, dans l'exemple précédent, le côté propriétaire serait OrderLine, et JPA conserverait l'association entre les lignes et l'ordre A, car les lignes ont une référence à A.

Une telle association serait cartographiée comme suit:

en ordre :

@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the 
   // inverse side, and that the mapping is defined by the attribute parentOrder 
   // at the other side of the association.
private Set<OrderLine> lines;

dans OrderLine:

@ManyToOne
private Order parentOrder;
55
JB Nizet

De plus, avoir @ManytoOne côté car le propriétaire n'aurait besoin que de n + 1 requêtes lors de la sauvegarde des associations. Où n est le nombre d'associations (plusieurs côté).

Considérant que @OneToMany en tant que propriétaire, tandis que l'insertion de l'entité parent (un côté) avec des associations (plusieurs côtés) entraînerait 2 * N + 1 requêtes. Dans laquelle une requête serait pour l'insertion de l'association et une autre requête serait pour la mise à jour de la clé étrangère dans l'entité associée.

4
userJ