707 votes

Différence entre FetchType LAZY et EAGER dans Java Persistence API ?

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 ?

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 ?

1364voto

Behrang Points 13471

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.

6 votes

@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 ?

103 votes

@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.

11 votes

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.

366voto

unbeli Points 9573

En gros,

LAZY = fetch when needed
EAGER = fetch immediately

19 votes

Très clair mais seulement après avoir lu la réponse de @Behang. Merci pour ce résumé clair :-)

83voto

Bozho Points 273663

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 )

0 votes

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 ?

0 votes

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).

1 votes

@Bozho Vous avez spécifié le chargement paresseux des collections uniquement. Un simple champ de type chaîne peut-il être chargé paresseusement ?

19voto

Kyung Min Points 51

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.

1 votes

Oui et ça a fait planter mon application jusqu'à ce que je passe à eager. Je suppose que la gestion des sessions est un art et une science en soi, mais JawsDB donne 10 connexions sur la version gratuite et pas beaucoup plus sur les versions payantes.

11voto

JDeveloper Points 1733

D'après mes connaissances, les deux types de recherche dépendent de vos besoins.

FetchType.LAZY est à la demande (c'est-à-dire lorsque nous avons besoin des données).

FetchType.EAGER est immédiate (c'est-à-dire qu'avant que notre besoin n'apparaisse, nous récupérons inutilement l'enregistrement).

Prograide.com

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.

Powered by:

X