juin
2006
Depuis la sortie de NHibernate 1.2.0.Alpha1, les associations et les collections sont « lazy » par défaut. Je pense qu’il est important de comprendre pourquoi.
(Existe-t-il un mot en français pour décemment remplacer « lazy » ?)
Je suis sure que la plus part des personnes migrant vers NH1.2.0 vont d’abord ajouter default-lazy= »false » à <hibernate-mapping> dans tous leurs mappings. Et cette opération est certainement très utile pour rendre son application fonctionnelle avec cette nouvelle version.
Mais je pense que cette modification a été faites pour changer la façon avec laquelle est développée une application utilisant NHibernate et augmenter l’usage du lazy loading (ce qui implique apprendre à utiliser des entités « lazy » efficacement). Cette modification a aussi été faite pour Hibernate (de H2.1 à H3).
La raison la plus évident d’utiliser le lazy loading est qu’on ne devrait pas charger des entités dont on n’a pas besoin (ce qui peut se produire lorsque le lazy loading n’est pas activé). C’est beaucoup plus efficace en temps et en ressource mémoire, améliorant les performances et la « scalabilité » de votre application.
Mais comme la plus part des techniques d’optimisation, cette fonctionnalité apporte beaucoup de petits problèmes:
D’abord, elle rend vos (un peu) plus conscient de la présence de l’ORM. Un des pré-requis est que les propriétés/méthodes des entités lazy doivent être virtuelles (une nouvelle fonctionnalité a été rajouté pour vérifier cela pour vous).
Lorsque vous avez besoin d’accéder à une association/collection qui est lazy, vous devez vous assurer que l’entité parent est attachée à une session NHibernate ouverte. Ce qui peut être fait en appelant soit une méthode Save/Update soit la méthode Lock de la session. Mais il est parfois assez difficile de le faire correctement dans certaines situations…
Ensuite, il arrive que vous sachiez, lorsque vous chargez une entité, que vous aurez aussi besoin de certaines de ces lazy associations/collections. Dans ces cas, Les APIs HQL et ICriteria sont d’un grand secours. Elles permettent de charger ces informations à même temps que l’entité parent, et ainsi éviter le problème « n+1 selects » (qui survient lorsque les entités lazy sont chargées une par une à leur premier accès).
Enfin, il est important de comprendre que, lorsque le « lazy loading » n’est pas activé sur une association/collection, il est impossible d’éviter son chargement (HQL/ICriteria APIs ne le permettent pas). Vous pouvez le faire lorsque vous savez que vous utiliserez toujours ce lien (ou lorsque vous préférez un éventuel impact sur les performances plutôt que de résoudre les problèmes liés au lazy loading :D)
Mon conseil, c’est de rendre/laisser les associations et collections lazy et d’écrire de bonnes requêtes pour récupérer les informations dont on a réellement besoin.