241 lines
14 KiB
XML
241 lines
14 KiB
XML
<?xml version="1.0" encoding="iso-8859-1"?>
|
|
<chapter id="best-practices" revision="3">
|
|
<title>Meilleures pratiques</title>
|
|
|
|
<variablelist spacing="compact">
|
|
<varlistentry>
|
|
<term>Découpez finement vos classes et mappez les en utilisant <literal><component></literal>.</term>
|
|
<listitem>
|
|
<para>
|
|
Utilisez une classe <literal>Adresse</literal> pour encapsuler <literal>Rue</literal>,
|
|
<literal>Region</literal>, <literal>CodePostal</literal>.
|
|
Ceci permet la réutilisation du code et simplifie la maintenance.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Déclarez des propriétés d'identifiants dans les classes persistantes.</term>
|
|
<listitem>
|
|
<para>
|
|
Hibernate rend les propriétés d'identifiants optionnelles. Il existe beaucoup de raisons
|
|
pour lesquelles vous devriez les utiliser. Nous recommandons que vous utilisiez des identifiants
|
|
techniques (générés, et sans connotation métier).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Identifiez les clefs naturelles.</term>
|
|
<listitem>
|
|
<para>
|
|
Identifiez les clefs naturelles pour toutes les entités, et mappez les avec
|
|
<literal><natural-id></literal>. Implémentez <literal>equals()</literal> et
|
|
<literal>hashCode()</literal> pour comparer les propriétés qui composent la clef naturelle.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Placez chaque mapping de classe dans son propre fichier.</term>
|
|
<listitem>
|
|
<para>
|
|
N'utilisez pas un unique document de mapping. Mappez <literal>com.eg.Foo</literal> dans
|
|
le fichier <literal>com/eg/Foo.hbm.xml</literal>. Cela prend tout son sens lors
|
|
d'un travail en équipe.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Chargez les mappings comme des ressources.</term>
|
|
<listitem>
|
|
<para>
|
|
Déployez les mappings en même temps que les classes qu'ils mappent.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Pensez à externaliser les chaînes de caractères.</term>
|
|
<listitem>
|
|
<para>
|
|
Ceci est une bonne habitude si vos requêtes appellent des fonctions SQL qui ne sont
|
|
pas au standard ANSI. Cette externalisation dans les fichiers de mapping rendra votre
|
|
application plus portable.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Utilisez les variables "bindées".</term>
|
|
<listitem>
|
|
<para>
|
|
Comme en JDBC, remplacez toujours les valeurs non constantes par "?". N'utilisez jamais
|
|
la manipulation des chaînes de caractères pour remplacer des valeurs non constantes dans
|
|
une requête ! Encore mieux, utilisez les paramètres nommés dans les requêtes.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Ne gérez pas vous même les connexions JDBC.</term>
|
|
<listitem>
|
|
<para>
|
|
Hibernate laisse l'application 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,
|
|
réfléchissez à l'idée de fournir votre propre implémentation de <literal>org.hibernate.connection.ConnectionProvider</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Pensez à utiliser les types utilisateurs.</term>
|
|
<listitem>
|
|
<para>
|
|
Supposez que vous ayez une 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
|
|
<literal>org.hibernate.UserType</literal>.Cette approche libère le code de l'application
|
|
de l'implémentation des transformations vers / depuis les types Hibernate.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Utilisez du JDBC pur dans les goulets d'étranglement.</term>
|
|
<listitem>
|
|
<para>
|
|
Dans certaines parties critiques de votre système d'un point de vue performance, quelques opérations
|
|
peuvent tirer partie d'un appel JDBC natif.
|
|
Mais attendez de <emphasis>savoir</emphasis>
|
|
que c'est un goulet d'étranglement. Ne supposez jamais qu'un appel JDBC sera forcément plus
|
|
rapide. Si vous avez besoin d'utiliser JDBC directement, ouvrez une <literal>Session</literal>
|
|
Hibernate et utilisez la connexion SQL sous-jacente. Ainsi vous pourrez utiliser la même stratégie
|
|
de transation et la même gestion des connexions.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Comprendre le flush de <literal>Session</literal>.</term>
|
|
<listitem>
|
|
<para>
|
|
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 opérations menées dans une transaction particulière.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Dans une architecture à trois couches, pensez à utiliser <literal>saveOrUpdate()</literal>.</term>
|
|
<listitem>
|
|
<para>
|
|
Quand vous utilisez une architecture à base de servlet / session bean, vous pourriez 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 <literal>Session.merge()</literal> ou <literal>Session.saveOrUpdate()</literal> pour
|
|
synchroniser les objets avec la base de données.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Dans une architecture à deux couches, pensez à utiliser la déconnexion de session.</term>
|
|
<listitem>
|
|
<para>
|
|
Les transactions de bases de données doivent être aussi courtes que possible
|
|
pour une meilleure montée en charge.Cependant, il est souvent nécessaire d'implémenter
|
|
de longues <emphasis>transactions applicatives</emphasis>, 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 à 2 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 vous travaillerez avec des
|
|
données périmées.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Considérez que les exceptions ne sont pas rattrapables.</term>
|
|
<listitem>
|
|
<para>
|
|
Il s'agit plus d'une pratique obligatoire que d'une "meilleure pratique". Quand une exception
|
|
intervient, il faut faire un rollback de la <literal>Transaction</literal> et
|
|
fermer la <literal>Session</literal>.
|
|
Sinon, Hibernate ne peut garantir l'intégrité des états persistants en mémoire. En particulier,
|
|
n'utilisez pas <literal>Session.load()</literal> pour déterminer si une instance avec un identifiant
|
|
donné existe en base de données, utilisez <literal>Session.get()</literal> ou un requête.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Préférez le chargement tardif des associations.</term>
|
|
<listitem>
|
|
<para>
|
|
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 assocations de classes en cache, où il y a une extrêmement
|
|
forte probabilité que l'élément soit en cache, désactivez explicitement le chargement
|
|
par jointures ouvertes en utilisant <literal>outer-join="false"</literal>.
|
|
Lorsqu'un chargement par jointure ouverte est approprié pour un cas d'utilisation
|
|
particulier, utilisez une requête avec un <literal>left join fetch</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>
|
|
Utilisez le pattern <emphasis>d'une ouverture de session dans une vue</emphasis>,
|
|
ou une <emphasis>phase d'assemblage</emphasis> disciplinée pour éviter des problèmes
|
|
avec des données non rapatriées.
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
Hibernate libère les développeurs de l'écriture fastidieuse des <emphasis>objets de transfert
|
|
de données (NdT : Data Transfer Objects)</emphasis> (DTO). Dans une architecture EJB traditionnelle,
|
|
les DTOs ont deux buts : premièrement, ils contournent le problème des "entity bean" 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 DTOs avant de retourner sous le
|
|
contrôle de la couche de présentation. Hibernate élimine le premier but. Pourtant, 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 à propos de quelles données sont 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.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Pensez à abstraite votre logique métier d'Hibernate.</term>
|
|
<listitem>
|
|
<para>
|
|
Cachez le mécanisme d'accès aux données (Hibernate) derrière une interface. Combinez les patterns
|
|
<emphasis>DAO</emphasis> et <emphasis>Thread Local Session</emphasis>. Vous pouvez même avoir quelques
|
|
classes persistées par du JDBC pur, associées à Hibernate via un <literal>UserType</literal> (ce conseil est
|
|
valable pour des applications de taille respectables ; il n'est pas valable pour une application
|
|
avec cinq tables).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>N'utilisez pas d'associations de mapping exotiques.</term>
|
|
<listitem>
|
|
<para>
|
|
De bons cas d'utilisation pour de vraies associations plusieurs-vers-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-vers-plusieurs vers une classe
|
|
de liaisons intermédiaire. En fait, nous pensons que la plupart des associations sont
|
|
de type un-vers-plusieurs ou plusieurs-vers-un, vous devez être très attentifs lorsque
|
|
vous utilisez autre chose et vous demander si c'est vraiment nécessaire.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term>Préférez les associations bidirectionnelles.</term>
|
|
<listitem>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
</chapter>
|
|
|