J'ai remarqué dans le code source d'Hibernate que le mappage FetchType par défaut pour ManyToOne est EAGER. Alors que pour le mappage OnetoMany, le type de chargement par défaut est Lazy. Quelle est la raison spécifique derrière cela?
Du spe JPA 2.0 c, les valeurs par défaut sont les suivantes:
OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER
Et en hibernation, tout est paresseux
Depuis Hibernate Docs,
Par défaut, Hibernate utilise l'extraction de sélection paresseuse pour les collections et l'extraction de proxy paresseux pour les associations à valeur unique. Ces valeurs par défaut sont valables pour la plupart des associations dans la majorité des applications.
Pour répondre à votre question, Hibernate est une implémentation de la norme JPA. Hibernate a ses propres bizarreries de fonctionnement, mais selon les documents Hibernate
By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
Ainsi, Hibernate chargera toujours n'importe quel objet à l'aide d'une stratégie de récupération paresseuse, quel que soit le type de relation que vous avez déclaré.
La spécification JPA suppose qu'en général la plupart des applications requièrent que les relations singleton par défaut soient enthousiastes, tandis que les relations multi-valeurs par défaut soient paresseuses.
Reportez-vous ici pour plus
La raison de leur définition sur EAGER était due au fait que les premiers concepteurs de JPA 1.0 supposaient que l'application des implémentations JPA pour prendre en charge l'initialisation dynamique des proxys serait une exigence très forte. Cependant, comme sans proxy, les performances en souffriraient énormément, tous les fournisseurs prennent en charge les associations LAZY.
Utilisation de la stratégie de récupération EAGER par défaut pour @ManyToOne
et @OneToOne
les associations sont ne odeur de code .
Comme expliqué dans cet article , je vous suggère de définir toutes les associations comme LAZY et d'utiliser la directive JOIN FETCH disponible dans chaque requête HQL/JPQL ou Criteria.
Dans Hibernate, OneToOne et ManyToOne par défaut ne seront pas paresseux même si vous le définissez explicitement comme paresseux.
Exemple: il existe une association Parent-> Enfant. Par défaut, cela signifie que la colonne PARENT_ID
Se trouve dans la table CHILD
. ORM ne sait pas si votre parent a réellement un enfant ou s'il est nul. S'il y a un enfant, un objet doit être défini en tant que champ sur Parent. S'il est nul, l'ORM doit définir null. Pour savoir si elle est nulle ou non, ORM doit interroger la table CHILD. Puisqu'une requête est faite de toute façon, il est logique de renvoyer Child immédiatement s'il existe.
Donc, pour rendre MTO ou OTO paresseux, vous devez indiquer à ORM que Child existe toujours (en le rendant non facultatif, alias requis, alias non nul). Par conséquent, ORM sait qu'il est toujours présent et sait qu'il peut définir un proxy au lieu de Child.
Vous pouvez également conserver la colonne CHILD_ID dans la table PARENT. Ensuite, si Child est nul, la valeur de l'enregistrement sera également nulle. Mais pour cela, vous devez ajouter des options de configuration (comme @JoinColumn
), Ce n'est pas une option par défaut.
si vous utilisez lazyfetch dans ManyToOne, vous devez utiliser join lorsque vous effectuez une requête qui obtient tous les modèles du côté plusieurs
Si vous l'examinez attentivement, vous constaterez que si la relation se termine par le mot clé Many
, c'est-à-dire OneToMany
, ManyToMany
, il s'agit de Lazy. S'il se termine par One
c'est-à-dire ManyToOne
, OneToOne
, c'est Désireux. Donc, si vous devez charger un seul objet, il le récupérera très rapidement. Mais s'il charge de nombreux objets, cela prendra beaucoup de temps. Ainsi, pour arrêter ce temps de chargement par défaut, ils devraient l'avoir défini sur le chargement paresseux.