hibernate-orm/doc/reference/fr/modules/best_practices.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>&lt;component&gt;</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>&lt;natural-id&gt;</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>