Hibernate.orgCommunity Documentation

Chapitre 25. Meilleures pratiques

Découpez finement vos classes et mappez-les en utilisant <component> :

Utilisez une classe Address pour résumer street, suburb, state, postcode. Ceci permet la réutilisation du code et simplifie la maintenance.

Déclarez des propriétés d'identifiants dans les classes persistantes :

Hibernate rend les propriétés d'identifiants optionnelles. Il est recommandé de les utiliser pour de nombreuses raisons. Utilisez les identifiants comme 'synthetic' (générés, et sans connotation métier).

Identifiez les clefs naturelles :

Identifiez les clefs naturelles pour toutes les entités, et mappez-les avec <natural-id>. Implémentez equals() et hashCode() pour comparer les propriétés qui composent la clef naturelle.

Placez chaque mapping de classe dans son propre fichier :

N'utilisez pas un unique document de mapping. Mappez com.eg.Foo dans le fichier com/eg/Foo.hbm.xml. Cela prend tout son sens lors d'un travail en équipe.

Chargez les mappings comme des ressources :

Déployez les mappings en même temps que les classes qu'ils mappent.

Pensez à externaliser les chaînes de requêtes :

Ceci est une bonne habitude si vos requêtes appellent des fonctions SQL qui ne sont pas au standard ANSI. Cette externalisation des chaînes de requête dans les fichiers de mapping rendra votre application plus portable.

Utilisez les variables bindées.

Comme dans JDBC, remplacez toujours les valeurs non constantes par "?". N'utilisez jamais la manipulation des chaînes de caractères pour lier des valeurs non constantes dans une requête ! Encore mieux, utilisez les paramètres nommés dans les requêtes.

Ne gérez pas vous-même les connexions JDBC :

Hibernate permet à l'application de gérer les connexions JDBC. Vous ne devriez gérer vos connexions qu'en dernier recours. Si vous ne pouvez pas utiliser les systèmes de connexions livrés, considérez la fourniture de votre propre implémentation de org.hibernate.connection.ConnectionProvider.

Considérez l'utilisation de types personnalisés :

Supposez que vous ayez un type Java, de telle bibliothèque, qui a besoin d'être persisté mais qui ne fournit pas les accesseurs nécessaires pour le mapper comme composant. Vous devriez implémenter org.hibernate.UserType. Cette approche évite au code de l'application, l'implémentation de transformations vers / depuis les types Hibernate.

Utilisez du JDBC pur dans les goulots d'étranglement :

In performance-critical areas of the system, some kinds of operations might benefit from direct JDBC. Do not assume, however, that JDBC is necessarily faster. Please wait until you know something is a bottleneck. If you need to use direct JDBC, you can open a Hibernate Session, wrap your JDBC operation as a org.hibernate.jdbc.Work object and using that JDBC connection. This way you can still use the same transaction strategy and underlying connection provider.

Comprenez le flush de Session :

De temps en temps la Session synchronise ses états persistants avec la base de données. Les performances seront affectées si ce processus arrive trop souvent. Vous pouvez parfois minimiser les flush non nécessaires en désactivant le flush automatique ou même en changeant l'ordre des requêtes et autres opérations effectuées dans une transaction particulière.

Dans une architecture à trois couches, vous pouvez utilisez des objets détachés :

Quand vous utilisez une architecture à base de servlet / session bean, vous pouvez passer des objets chargés dans le bean session vers et depuis la couche servlet / JSP. Utilisez une nouvelle session pour traiter chaque requête. Utilisez Session.merge() ou Session.saveOrUpdate() pour synchroniser les objets avec la base de données.

Dans une architecture à deux couches, pensez à utiliser les contextes de persistance longue :

Les transactions de bases de données doivent être aussi courtes que possible pour une meilleure extensibilité. Cependant, il est souvent nécessaire d'implémenter de longues transactions applicatives, une simple unité de travail du point de vue de l'utilisateur. Une transaction applicative peut s'étaler sur plusieurs cycles de requêtes/réponses du client. Il est commun d'utiliser des objets détachés pour implémenter des transactions applicatives. Une alternative, extrêmement appropriée dans une architecture à deux couches, est de maintenir un seul contact de persistance ouvert (session) pour toute la durée de vie de la transaction applicative et simplement se déconnecter de la connexion JDBC à la fin de chaque requête, et se reconnecter au début de la requête suivante. Ne partagez jamais une seule session avec plus d'une transaction applicative, ou bien vous travaillerez avec des données périmées.

Considérez que les exceptions ne sont pas rattrapables :

Il s'agit plus d'une pratique obligatoire que d'une "meilleure pratique". Quand une exception intervient, il faut faire un rollback de la Transaction et fermer la Session. Sinon, Hibernate ne peut garantir l'intégrité des états persistants en mémoire. En particulier, n'utilisez pas Session.load() pour déterminer si une instance avec l'identifiant donné existe en base de données, à la place utilisez Session.get() ou une requête.

Préférez le chargement différé des associations :

Utilisez le chargement complet avec modération. Utilisez les proxies et les collections chargées tardivement pour la plupart des associations vers des classes qui ne sont pas susceptibles d'être complètement retenues dans le cache de second niveau. Pour les associations de classes en cache, où il y a une forte probabilité que l'élément soit en cache, désactivez explicitement le chargement par jointures ouvertes en utilisant outer-join="false". Lorsqu'un chargement par jointure ouverte est approprié pour un cas d'utilisation particulier, utilisez une requête avec un left join fetch.

Utilisez le pattern d'une ouverture de session dans une vue, ou une phase d'assemblage disciplinée pour éviter des problèmes avec des données non rapatriées :

Hibernate libère les développeurs de l'écriture fastidieuse des objets de transfert de données (DTO). Dans une architecture EJB traditionnelle, les DTO ont deux buts : premièrement, ils contournent le problème des beans entités qui ne sont pas sérialisables ; deuxièmement, ils définissent implicitement une phase d'assemblage où toutes les données utilisées par la vue sont rapatriées et organisées dans les DTO avant de retourner sous le contrôle de la couche de présentation. Hibernate élimine le premier but. Cependant, vous aurez encore besoin d'une phase d'assemblage (pensez à vos méthodes métier comme ayant un contrat strict avec la couche de présentation, en ce qui concerne les données disponibles dans les objets détachés) à moins que vous soyez préparés à garder le contexte de persistance (la session) ouvert à travers tout le processus de rendu de la vue. Ceci ne représente pas une limitation de Hibernate! Au contraire c'est une exigence fondamentale d'un accès sécurisé aux données transactionnelles.

Pensez à abstraire votre logique métier d'Hibernate :

Cachez le mécanisme d'accès aux données (Hibernate) derrière une interface. Combinez les modèles DAO et Thread Local Session. Vous pouvez même avoir quelques classes persistées par du JDBC pur, associées à Hibernate via un UserType (ce conseil est valable pour des applications de taille respectables ; il n'est pas valable pour une application avec cinq tables).

N'utilisez pas d'associations de mapping exotiques :

Les utilisations appropriées de vraies associations plusieurs-à-plusieurs sont rares. La plupart du temps vous avez besoin d'informations additionnelles stockées dans la table d'association. Dans ce cas, il est préférable d'utiliser deux associations un-à-plusieurs vers une classe de liaisons intermédiaire. En fait, nous pensons que la plupart des associations sont de type un-à-plusieurs ou plusieurs-à-un, vous devez être très prudent lorsque vous utilisez toute autre association et vous demander si c'est vraiment nécessaire.

Préférez les associations bidirectionnelles :

Les associations unidirectionnelles sont plus difficiles à questionner. Dans une grande application, la plupart des associations devraient être navigables dans les deux directions dans les requêtes.