Quelle est la différence entre:
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)
@JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")
private List<Branch> branches;
...
}
et
@Entity
public class Company {
@OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY, mappedBy = "companyIdRef")
private List<Branch> branches;
...
}
Réponses:
L'annotation
@JoinColumn
indique que cette entité est le propriétaire de la relation (c'est-à-dire que la table correspondante a une colonne avec une clé étrangère vers la table référencée), tandis que l'attributmappedBy
indique que l'entité de ce côté est l'inverse de la relation, et le propriétaire réside dans «l'autre» entité. Cela signifie également que vous pouvez accéder à l'autre table à partir de la classe que vous avez annotée avec "mappedBy" (relation entièrement bidirectionnelle).En particulier, pour le code dans la question, les annotations correctes ressembleraient à ceci:
la source
@JoinColumn
dansCompany
Branch
n'a pas de propriété qui fait référenceCompany
, mais la table sous-jacente a une colonne qui le fait, vous pouvez l'utiliser@JoinTable
pour la mapper. Il s'agit d'une situation inhabituelle, car vous mapperiez normalement la colonne de l'objet qui correspond à sa table, mais cela peut arriver et c'est parfaitement légitime.@OneToOne
, les lignes enfants sont mises à jour avec unnull
dans leur colonne FKey qui fait référence au parent.@JoinColumn
pourrait être utilisé des deux côtés de la relation. La question portait sur l'utilisation@JoinColumn
sur le@OneToMany
côté (cas rare). Et le point ici est dans la duplication d'informations physiques (nom de colonne) avec une requête SQL non optimisée qui produira desUPDATE
instructions supplémentaires .Selon la documentation :
Étant donné que plusieurs à un sont (presque) toujours le côté propriétaire d'une relation bidirectionnelle dans la spécification JPA, l'association un à plusieurs est annotée par
@OneToMany(mappedBy=...)
Troop
a une relation un à plusieurs bidirectionnelle avecSoldier
la propriété de la troupe. Vous n'avez pas (ne devez pas) définir de mappage physique sur lemappedBy
côté.Pour mapper un un à plusieurs bidirectionnel, avec le côté un à plusieurs comme côté propriétaire , vous devez supprimer l'
mappedBy
élément et définir le plusieurs à un@JoinColumn
commeinsertable
etupdatable
à faux. Cette solution n'est pas optimisée et produira desUPDATE
instructions supplémentaires .la source
mappedBy="troop"
référence à quel champ?mappedBy="troop"
fait référence à la troupe de propriété de la classe Soldat. Dans le code ci-dessus, la propriété n'est pas visible car ici Mykhaylo l'a omise, mais vous pouvez déduire son existence par le getter getTroop (). Vérifiez la réponse d' Óscar López , elle est très claire et vous obtiendrez le point.Association un-à-plusieurs unidirectionnelle
Comme je l'ai expliqué dans cet article , si vous utilisez l'
@OneToMany
annotation avec@JoinColumn
, vous avez alors une association unidirectionnelle, comme celle entre l'Post
entité parent et l'enfantPostComment
dans le diagramme suivant:Lorsque vous utilisez une association un-à-plusieurs unidirectionnelle, seul le côté parent mappe l'association.
Dans cet exemple, seule l'
Post
entité définira une@OneToMany
association avec l'PostComment
entité enfant :Association un-à-plusieurs bidirectionnelle
Si vous utilisez le
@OneToMany
avec l'mappedBy
ensemble d'attributs, vous avez une association bidirectionnelle. Dans notre cas, l'Post
entité a une collection d'PostComment
entités enfants et l'PostComment
entité enfant a une référence à l'Post
entité parent , comme illustré par le diagramme suivant:Dans l'
PostComment
entité, lapost
propriété de l' entité est mappée comme suit:Dans l'
Post
entité, l'comments
association est mappée comme suit:L'
mappedBy
attribut de l'@OneToMany
annotation fait référence à lapost
propriété dans l'PostComment
entité enfant et, de cette façon, Hibernate sait que l'association bidirectionnelle est contrôlée par le@ManyToOne
côté, qui est chargé de gérer la valeur de colonne de clé étrangère sur laquelle cette relation de table est basée.Pour une association bidirectionnelle, vous devez également disposer de deux méthodes utilitaires, comme
addChild
etremoveChild
:Ces deux méthodes garantissent que les deux côtés de l'association bidirectionnelle ne sont pas synchronisés. Sans synchronisation des deux extrémités, Hibernate ne garantit pas que les changements d'état d'association se propageront à la base de données.
Lequel choisir?
L' association unidirectionnelle
@OneToMany
ne fonctionne pas très bien , vous devez donc l'éviter.Il vaut mieux utiliser le bidirectionnel
@OneToMany
qui est plus efficace .la source
L'annotation mappedBy devrait idéalement toujours être utilisée dans le côté parent (classe Company) de la relation bidirectionnelle, dans ce cas, elle devrait être dans la classe Company pointant vers la variable membre 'company' de la classe Child (classe Branch).
L'annotation @JoinColumn est utilisée pour spécifier une colonne mappée pour rejoindre une association d'entité, cette annotation peut être utilisée dans n'importe quelle classe (Parent ou Enfant) mais elle devrait idéalement être utilisée uniquement d'un côté (soit dans la classe parent soit dans la classe Child non dans les deux) ici, dans ce cas, je l'ai utilisé dans le côté enfant (classe Branch) de la relation bidirectionnelle indiquant la clé étrangère dans la classe Branch.
ci-dessous est l'exemple de travail:
classe parent, Entreprise
classe enfant, branche
la source
Je voudrais juste ajouter que
@JoinColumn
cela ne doit pas toujours être lié à l' emplacement des informations physiques comme le suggère cette réponse. Vous pouvez combiner@JoinColumn
avec@OneToMany
même si la table parent n'a pas de données de table pointant vers la table enfant.Comment définir une relation OneToMany unidirectionnelle dans JPA
OneToMany unidirectionnel, pas de ManyToOne inverse, pas de table de jointure
Il ne semble cependant être disponible qu'en
JPA 2.x+
. Il est utile dans les situations où vous souhaitez que la classe enfant contienne simplement l'ID du parent, et non une référence complète.la source
Je ne suis pas d'accord avec la réponse acceptée ici par Óscar López. Cette réponse est inexacte!
Ce n'est PAS
@JoinColumn
ce qui indique que cette entité est le propriétaire de la relation. C'est plutôt l'@ManyToOne
annotation qui fait cela (dans son exemple).Les annotations de relation telles que
@ManyToOne
,@OneToMany
et@ManyToMany
indiquent à JPA / Hibernate de créer un mappage. Par défaut, cela se fait via une table de jointure distincte.@JoinColumn
MappedBy
Rappelez-vous:
MappedBy
est une propriété des annotations de relations dont le but est de générer un mécanisme pour relier deux entités, ce qu'elles font par défaut en créant une table de jointure.MappedBy
arrête ce processus dans une direction.L'entité qui n'utilise pas
MappedBy
est réputée être le propriétaire de la relation, car la mécanique du mappage est dictée au sein de sa classe par l'utilisation de l'une des trois annotations de mappage par rapport au champ de clé étrangère. Cela spécifie non seulement la nature du mappage, mais donne également des instructions sur la création d'une table de jointure. En outre, l'option de suppression de la table de jointure existe également en appliquant l'annotation @JoinColumn sur la clé étrangère qui la conserve à l'intérieur de la table de l'entité propriétaire.Donc en résumé:
@JoinColumn
soit crée une nouvelle colonne de jointure, soit renomme une colonne existante; tandis que leMappedBy
paramètre fonctionne en collaboration avec les annotations de relation de l'autre classe (enfant) afin de créer un mappage via une table de jointure ou en créant une colonne de clé étrangère dans la table associée de l'entité propriétaire.Pour illustrer le
MapppedBy
fonctionnement, considérez le code ci-dessous. Si leMappedBy
paramètre devait être supprimé, Hibernate créerait en fait DEUX tables de jointure! Pourquoi? Parce qu'il y a une symétrie dans les relations plusieurs-à-plusieurs et Hibernate n'a aucune raison de choisir une direction plutôt qu'une autre.Nous utilisons donc
MappedBy
pour dire à Hibernate, nous avons choisi l'autre entité pour dicter la cartographie de la relation entre les deux entités.L'ajout de @JoinColumn (name = "driverID") dans la classe propriétaire (voir ci-dessous), empêchera la création d'une table de jointure et, à la place, créera une colonne de clé étrangère driverID dans la table Cars pour construire un mappage:
la source
JPA est une API en couches, les différents niveaux ont leurs propres annotations. Le niveau le plus élevé est le (1) niveau d'entité qui décrit les classes persistantes, puis vous avez (2) le niveau de base de données relationnelle qui suppose que les entités sont mappées à une base de données relationnelle et (3) le modèle java.
Niveau 1 annotations:
@Entity
,@Id
,@OneToOne
,@OneToMany
,@ManyToOne
,@ManyToMany
. Vous pouvez introduire la persistance dans votre application en utilisant uniquement ces annotations de haut niveau. Mais ensuite, vous devez créer votre base de données selon les hypothèses que JPA fait. Ces annotations spécifient le modèle entité / relation.Niveau 2 annotations:
@Table
,@Column
,@JoinColumn
, ... Influence du mappage des entités / propriétés aux tables de base de données relationnelles / colonnes si vous n'êtes pas satisfait des réglages par défaut de l' APP ou si vous avez besoin de la carte à une base de données existante. Ces annotations peuvent être considérées comme des annotations d'implémentation, elles spécifient comment le mappage doit être effectué.À mon avis, il est préférable de s'en tenir autant que possible aux annotations de haut niveau, puis d'introduire les annotations de niveau inférieur selon les besoins.
Pour répondre aux questions: le
@OneToMany
/mappedBy
est plus agréable car il n'utilise que les annotations du domaine d'entité. Le@oneToMany
/@JoinColumn
est également correct, mais il utilise une annotation d'implémentation lorsque cela n'est pas strictement nécessaire.la source
Permettez-moi de faire simple.
Vous pouvez utiliser @JoinColumn de chaque côté indépendamment du mappage.
Divisons cela en trois cas.
1) Cartographie unidirectionnelle de la succursale à l'entreprise.
2) Cartographie bidirectionnelle de l'entreprise à la succursale.
3) Uniquement cartographie unidirectionnelle de l'entreprise à la succursale.
Ainsi, tout cas d'utilisation tombera dans ces trois catégories. Alors laissez-moi vous expliquer comment utiliser @JoinColumn et mappedBy .
1) Cartographie unidirectionnelle de la succursale à l'entreprise.
Utilisez JoinColumn dans la table Branch.
2) Cartographie bidirectionnelle de l'entreprise à la succursale.
Utilisez mappedBy dans le tableau Company comme décrit par la réponse de @Mykhaylo Adamovych.
3) Cartographie unidirectionnelle de l'entreprise à la succursale.
Utilisez simplement @JoinColumn dans la table Company.
Cela signifie que, sur la base du mappage de la clé étrangère "courseId" dans la table des branches, obtenez-moi la liste de toutes les branches. REMARQUE: dans ce cas, vous ne pouvez pas extraire une entreprise d'une succursale, seul le mappage unidirectionnel existe d'une entreprise à l'autre.
la source