J'ai tendance à utiliser Hibernate en combinaison avec Spring framework et ses capacités de démarcation déclarative des transactions (par exemple, @ Transactional ).
Comme nous le savons tous, hibernate essaie d'être aussi non invasif et aussi transparent que possible, mais cela prouve un un peu plus difficile lors de l'utilisation des relations lazy-loaded
.
Je vois un certain nombre d'alternatives de conception avec différents niveaux de transparence.
fetchType=FetchType.EAGER)
Hibernate.initialize(proxyObj);
initialize
, il n'est pas garanti que d'autres implémentations fournissent un équivalent.Model
persistants eux-mêmes (en utilisant proxy dynamique ou @Transactional
) loadData()
et loadDataWithDeps()
loadDataWithA()
, ...., loadDataWithX()
byId()
findZzzById(zid)
, puis getYyyIds(zid)
au lieu de z.getY()
loadData(id, fetchProfile);
Ai-je raté une option?
Quelle est votre approche préférée lorsque vous essayez de minimiser l'impact des relations lazy-loaded
Dans la conception de votre application?
(Oh, et désolé pour WoT )
Comme nous le savons tous, l'hibernation essaie d'être aussi non invasive et transparente que possible
Je dirais que l'hypothèse initiale est fausse. La persistance transaparente est un mythe, car l'application doit toujours prendre en charge le cycle de vie de l'entité et la taille du graphe d'objet en cours de chargement.
Notez qu'Hibernate ne peut pas lire les pensées, donc si vous savez que vous avez besoin d'un ensemble particulier de dépendances pour une opération particulière, vous devez exprimer vos intentions d'Hibernate d'une manière ou d'une autre.
De ce point de vue, les solutions qui expriment explicitement ces intentions (à savoir, 2, 4 et 7) semblent raisonnables et ne souffrent pas du manque de transparence.
Je ne sais pas à quel problème (causé par la paresse) vous faites allusion, mais pour moi, la plus grande difficulté est d'éviter de perdre le contexte de la session dans mes propres caches d'application. Cas typique:
foo
est chargé et placé dans une carte;foo.getBar()
(quelque chose qui n'a jamais été appelé auparavant et qui est évalué paresseux);Donc, pour résoudre ce problème, nous avons un certain nombre de règles:
OpenSessionInViewFilter
pour les applications Web);try/finally
) afin que les sous-classes n'aient pas à y penser;Comme vous pouvez le voir, cela est en effet loin d'être non invasif et transparent. Mais le coût est toujours supportable, à comparer avec le prix que je devrais payer pour un chargement enthousiaste. Le problème avec ce dernier est que cela conduit parfois à l'effet papillon lors du chargement d'un seul objet référencé, sans parler d'une collection d'entités. La consommation de mémoire, l'utilisation du processeur et la latence pour ne pas en dire plus sont également bien pires, donc je suppose que je peux vivre avec.
Un modèle très courant consiste à utiliser OpenEntityManagerInViewFilter si vous créez une application Web.
Si vous créez un service, j'ouvrirais le TX sur la méthode publique du service, plutôt que sur les DAO, car très souvent une méthode nécessite d'obtenir ou de mettre à jour plusieurs entités.
Cela résoudra toute "exception de chargement différé". Si vous avez besoin de quelque chose de plus avancé pour l'optimisation des performances, je pense que la récupération des profils est la voie à suivre.