Je suis novice en matière d'API de persistance Java et d'Hibernate.
Quelle est la différence entre FetchType.LAZY
y FetchType.EAGER
dans l'API de persistance Java ?
Je suis novice en matière d'API de persistance Java et d'Hibernate.
Quelle est la différence entre FetchType.LAZY
y FetchType.EAGER
dans l'API de persistance Java ?
Parfois, vous avez deux entités, il y a une relation entre eux. Par exemple, vous pourriez avoir une entité appelée Université et une autre entité appelée Étudiant.
L'Université de l'entité peut avoir certaines propriétés de base tels que l'id, le nom, l'adresse, etc. ainsi que d'une propriété appelée étudiants:
public class University {
private String id;
private String name;
private String address;
private List<Student> students;
// setters and getters
}
Maintenant, lorsque vous chargez une Université à partir de la base de données, JPA charge son id, le nom et l'adresse de champs pour vous. Mais vous avez deux options pour les étudiants: pour le charger avec le reste des champs (c'est à dire avec impatience) ou pour le charger à la demande (c'est à dire paresseusement) lorsque vous appelez de l'université getStudents() la méthode.
Lorsque l'université a beaucoup d'étudiants, il n'est pas efficace pour charger l'ensemble de ses étudiants avec elle quand ils ne sont pas nécessaires. Donc, dans les autres cas, vous pouvez déclarer que vous voulez que les élèves être chargé lorsqu'ils sont réellement nécessaires. Ceci est appelé le chargement paresseux.
@BehrangSaeedzadeh pouvez-vous énumérer quelques différences pratiques, ou les avantages et inconvénients de chaque type de chargement (autres que l'efficacité que vous avez mentionnée). Pourquoi voudrait-on utiliser le chargement rapide ?
@ADTC Pour que le chargement paresseux fonctionne, la session JDBC doit encore être ouverte lorsque les entités cibles veulent être chargées dans la mémoire en invoquant la méthode getter (par ex. 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, il arrive que nous ayons une architecture client/serveur (par exemple, un client Swing ou un serveur JEE) et que les entités/DTO soient transférées par câble au client. Dans ce cas également, le chargement paresseux ne fonctionne pas en raison de la façon dont les entités sont sérialisées par câble.
J'aimerais ajouter quelques informations supplémentaires à cette réponse tirée de mon livre - Pour économiser la mémoire, le chargement paresseux est généralement utilisé pour les relations un à plusieurs et plusieurs à plusieurs. Pour les relations un à un, on utilise généralement Eager.
EAGER
Le chargement des collections signifie qu'elles sont récupérées intégralement au moment où leur parent est récupéré. Ainsi, si vous avez Course
et il a List<Student>
tous les étudiants sont récupérés de la base de données au moment où le Course
est recherchée.
LAZY
d'autre part, signifie que le contenu de la section List
ne sont récupérés que lorsque vous essayez d'y accéder. Par exemple, en appelant course.getStudents().iterator()
. L'appel de toute méthode d'accès au List
va initier un appel à la base de données pour récupérer les éléments. Ceci est mis en œuvre en créant un Proxy autour de l'élément List
(ou Set
). Ainsi, pour vos collections paresseuses, les types concrets ne sont pas ArrayList
y HashSet
mais PersistentSet
y PersistentList
(ou PersistentBag
)
J'ai utilisé ce concept pour récupérer les détails d'une entité enfant, mais je ne vois pas de différence entre les deux. Lorsque je spécifie Eager fetch, il récupère tout et lorsque je le débogue, je vois "Bean deferred" au niveau de l'entité enfant. Lorsque je dis course.getStudents()
il lance une requête SQL (je l'ai vu sur la console). Dans le type Lazy fetch également, la même chose se produit. Alors, quelle est la différence ?
Les collections avides sont récupérées lorsque l'entité propriétaire est chargée. Les collections paresseuses sont récupérées lorsque vous y accédez. Si ce n'est pas le comportement que vous avez observé, il y a probablement quelque chose qui ne va pas dans votre environnement (par exemple, l'exécution d'anciennes versions d'une classe).
@Bozho Vous avez spécifié le chargement paresseux des collections uniquement. Un simple champ de type chaîne peut-il être chargé paresseusement ?
Je peux prendre en compte 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 les objets de données récupérés sans session. Pourquoi ?
Toutes les données sont récupérées lorsque les données marquées avides dans l'objet lorsque la session est connectée. Cependant, dans le cas de la stratégie de chargement paresseux, l'objet marqué par chargement paresseux ne récupère pas les données si la session est déconnectée (après session.close()
). Tout cela peut être fait par le proxy hibernate. La stratégie Eager permet aux données d'être encore disponibles après la fermeture de la session.
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.
2 votes
Le chargement plus rapide des collections signifie qu'elles sont récupérées intégralement au moment où leur parent est récupéré. Pendant le chargement EAGER, tout mon enfant est récupéré. L'enfant est récupéré dans le PersistentSet et le PersistentList (ou PersistentBag), dans le Persistent Bag, il est affiché comme une liste de tableaux. Est-ce correct ?