Je suis un débutant pour Java Persistence API et Hibernate.
Quelle est la différence entre FetchType.LAZY
et FetchType.EAGER
dans l'API Java Persistence?
Je suis un débutant pour Java Persistence API et Hibernate.
Quelle est la différence entre FetchType.LAZY
et FetchType.EAGER
dans l'API Java Persistence?
Réponses:
Parfois, vous avez deux entités et il y a une relation entre elles. Par exemple, vous pouvez avoir une entité appelée
University
et une autre entité appeléeStudent
et une université peut avoir plusieurs étudiants:L'entité University peut avoir certaines propriétés de base telles que id, nom, adresse, etc. ainsi qu'une propriété de collection appelée student qui renvoie la liste des étudiants pour une université donnée:
Désormais, lorsque vous chargez une université à partir de la base de données, JPA charge ses champs d'ID, de nom et d'adresse pour vous. Mais vous avez deux options pour charger les étudiants:
getStudents()
méthode de l'université .Lorsqu'une université compte de nombreux étudiants, il n'est pas efficace de charger tous ses étudiants avec elle, en particulier lorsqu'ils ne sont pas nécessaires et dans ce cas, vous pouvez déclarer que vous souhaitez que les étudiants soient chargés lorsqu'ils sont réellement nécessaires. C'est ce qu'on appelle le chargement paresseux.
Voici un exemple, où
students
est explicitement marqué pour être chargé avec impatience:Et voici un exemple où
students
est explicitement marqué pour être chargé paresseusement:la source
getStudents()
), mais parfois ce n'est pas possible, car au moment où cette méthode est appelée, la session est déjà fermée et l'entité détachée. De même, nous avons parfois une architecture client / serveur (par exemple Swing client / serveur JEE) et les entités / DTO sont transférées via le câble au client et, le plus souvent dans ces scénarios, le chargement paresseux ne fonctionnera pas en raison de la façon dont les entités sont sérialisés sur le fil.getStudents()
méthode pour la première fois, les résultats sont-ils mis en cache? afin que je puisse accéder à ces résultats plus rapidement la prochaine fois?Fondamentalement,
la source
EAGER
le chargement des collections signifie qu'elles sont entièrement récupérées au moment où leur parent est récupéré. Donc, si vous l'avez faitCourse
et que c'est le casList<Student>
, tous les étudiants sont extraits de la base de données au moment où ilsCourse
sont récupérés.LAZY
d'autre part signifie que le contenu duList
est récupéré uniquement lorsque vous essayez d'y accéder. Par exemple, en appelantcourse.getStudents().iterator()
. L'appel de n'importe quelle méthode d'accès sur leList
lancera un appel à la base de données pour récupérer les éléments. Ceci est implémenté en créant un proxy autour duList
(ouSet
). Donc pour vos collections paresseuses, les types concrets ne sont pasArrayList
etHashSet
, maisPersistentSet
etPersistentList
(ouPersistentBag
)la source
course.getStudents()
, il déclenche une requête SQL (vu cela sur console). Dans le type Lazy fetch également, la même chose se produit. Alors, quelle est la différence ??fetchtype = LAZY
celui par défaut même si essayez d'obtenir la collection avec le getter hibernete jette une erreur me disant qu'il ne peut pas évaluerJe peux considérer les performances et l'utilisation de la mémoire. Une grande différence est que la stratégie de récupération EAGER permet d'utiliser un objet de données récupéré sans session. Pourquoi?
Toutes les données sont extraites lorsqu'elles sont marquées avec empressement dans l'objet lorsque la session est connectée. Cependant, en cas de stratégie de chargement différé, l'objet marqué de chargement différé ne récupère pas les données si la session est déconnectée (après l'
session.close()
instruction). Tout cela peut être fait par un proxy d'hibernation. Une stratégie désireuse permet aux données d'être toujours disponibles après la fermeture de la session.la source
Selon ma connaissance, les deux types de récupération dépendent de vos besoins.
FetchType.LAZY
est sur demande (c'est-à-dire lorsque nous avons demandé les données).FetchType.EAGER
est immédiat (c'est-à-dire avant que notre exigence ne vienne, nous récupérons inutilement l'enregistrement)la source
Par défaut, pour tous les objets de collection et de mappage, la règle d'extraction est
FetchType.LAZY
et pour les autres instances, elle suit laFetchType.EAGER
politique.En bref,
@OneToMany
et les@ManyToMany
relations ne récupèrent pas implicitement les objets associés (collection et carte) mais l'opération de récupération est répercutée en cascade dans le champ in@OneToOne
et@ManyToOne
ones.(courtoisie: - objectdbcom)
la source
Les deux
FetchType.LAZY
etFetchType.EAGER
sont utilisés pour définir le plan de récupération par défaut .Malheureusement, vous ne pouvez remplacer que le plan de récupération par défaut pour la récupération paresseuse. La récupération EAGER est moins flexible et peut entraîner de nombreux problèmes de performances .
Mon conseil est de limiter l'envie de rendre vos associations EAGER car aller chercher est une responsabilité en temps de requête. Ainsi, toutes vos requêtes doivent utiliser la directive fetch pour récupérer uniquement ce qui est nécessaire pour l'analyse de rentabilisation actuelle.
la source
Depuis le Javadoc :
Par exemple, désireux est plus proactif que paresseux. Lazy ne se produit que lors de la première utilisation (si le fournisseur prend le conseil), alors qu'avec les choses désireuses (peut) être récupérées à l'avance.
la source
Le
Lazy
type d'extraction est par défaut sélectionné par Hibernate sauf si vous marquez explicitement leEager
type d'extraction. Pour être plus précis et concis, la différence peut être indiquée comme ci-dessous.FetchType.LAZY
= Cela ne charge pas les relations sauf si vous l'invoquez via la méthode getter.FetchType.EAGER
= Cela charge toutes les relations.Avantages et inconvénients de ces deux types de récupération.
Lazy initialization
améliore les performances en évitant les calculs inutiles et en réduisant les besoins en mémoire.Eager initialization
prend plus de mémoire et la vitesse de traitement est lente.Cela dit, selon la situation, l'une ou l'autre de ces initialisations peut être utilisée.
la source
getMember
soit appelée qui corresponde exactement au modèle de nom du membre?Book.java
Subject.java
HibernateUtil.java
Main.java
Vérifiez la méthode retrieve () de Main.java. Lorsque nous obtenons Subject, sa liste de collections Books , annotée avec
@OneToMany
, sera chargée paresseusement. Mais, d'autre part, l'association liée au sujet de la collection Books , annotée avec@ManyToOne
, se charge avec précaution (par[default][1]
pour@ManyToOne
,fetchType=EAGER
). Nous pouvons changer le comportement en plaçant fetchType.EAGER sur@OneToMany
Subject.java ou fetchType.LAZY@ManyToOne
dans Books.java.la source
La source
la source
Je veux ajouter cette note à ce que "Kyung Hwan Min" a dit ci-dessus.
Supposons que vous utilisez Spring Rest avec cet architecte simple:
Et vous souhaitez renvoyer certaines données à l'interface, si vous utilisez
FetchType.LAZY
, vous obtiendrez une exception après avoir renvoyé des données à la méthode du contrôleur puisque la session est fermée dans le service afin que leJSON Mapper Object
ne puisse pas obtenir les données.Il existe trois options courantes pour résoudre ce problème, cela dépend de la conception, des performances et du développeur:
FetchType.EAGER
, pour que la session soit toujours en vie à la méthode du contrôleur.FetchType.LAZY
avec la méthode du convertisseur pour transférer des données d'Entity
un autre objet de donnéesDTO
et les envoyer au contrôleur, il n'y a donc aucune exception si la session est fermée.la source
Salut, j'ai joint 2 photos pour vous aider à comprendre cela.
la source
@ drop-shadow si vous utilisez Hibernate, vous pouvez appeler
Hibernate.initialize()
lorsque vous appelez lagetStudents()
méthode:la source
LAZY: Il récupère les entités enfants paresseusement, c'est-à-dire qu'au moment de la récupération de l'entité parent, il récupère simplement le proxy (créé par cglib ou tout autre utilitaire) des entités enfants et lorsque vous accédez à une propriété de l'entité enfant, il est en fait récupéré par hibernate.
EAGER: il récupère les entités enfants avec le parent.
Pour une meilleure compréhension, consultez la documentation Jboss ou vous pouvez utiliser
hibernate.show_sql=true
pour votre application et vérifier les requêtes émises par l'hibernate.la source