Thursday, January 04, 2007

Utilisation d'Hibernate

Pour faire suite au post précédent, j'ai observé que certaines applications sont construites sans tenir compte des limites et contraintes d'Hibernate... ils utilisent cette librairie comme le "silver bullet" qui va se charger de tout ce qui touche la question de la persistance et ce sans effort ou configuration spéciale!


Par exemple concernant l'utilisation du Paramètre Lazy dans le mapping, plusieurs applications sont configurées avec lazy=false. Ceci facilite évidemment la question du fetching des graphes d'objet, mais ceci à un prix et ce prix s'appelle performance!


Recommandation:

Pratiquement toutes les entités et les associations de compositions devraient être configurées de façon Lazy (i.e. lazy=”true”). Il ne faut pas confondre le paramètre lazy et le paramètre fetch, le premier indique seulement à Hibernate s’il pourra créer un proxy (qui exigera une initialisation en session ouverte) pour la classe en question ou la collection, tandis que dernier indique comment les relations doivent être fetchées (eager ou non).

En utilisant lazy=”false” ceci a comme « side-effect » de pre-fetché toutes les dépendances de l’entité et ultimement la base de donnée complète sera chargée en objet ! Cela peut être pratique puisqu’on n'a pas à se poser la question de devoir initialiser ou pas les dépendances, mais ça devient vite catastrophique lorsque le volume de donnée est important.

La décision de fetcher ou ne pas fetcher (eager fetch) est une stratégie qui doit être défini en runtime puisque différente utilisation exige différent accès aux données. La couche DAO peut être utilisée en ce sens en fournissant des options de loader ou ne pas loader les dépendances (avec Hibernate.initialize()) avant de fermer la session Hibernate. Configurer avec lazy=”false” élimine tout simplement cette flexibilité.

Si pour une raison quelconque, une dépendance d’une entité doit toujours être pre-fetché, alors utiliser l’option fetch=join dans le mapping mais en gardant le lazy à false pour cette entité dépendante.

L’auteur d’Hibernate a lui-même reconnu ce fait et recommande depuis Hibernate 3.0 que toutes les mapping des class et des collections soient lazy= ‘true’ (ceci est maintenant le défaut utilisé).

Martin