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<EFBFBD>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<EFBFBD>clarez des propri<72>t<EFBFBD>s d'identifiants dans les classes persistantes.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Hibernate rend les propri<72>t<EFBFBD>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<EFBFBD>r<EFBFBD>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<69>s, et mappez les avec
|
|||
|
<literal><natural-id></literal>. Impl<70>mentez <literal>equals()</literal> et
|
|||
|
<literal>hashCode()</literal> pour comparer les propri<72>t<EFBFBD>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 <20>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 <20> externaliser les cha<68>nes de caract<63>res.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Ceci est une bonne habitude si vos requ<71>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<6E>es".</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Comme en JDBC, remplacez toujours les valeurs non constantes par "?". N'utilisez jamais
|
|||
|
la manipulation des cha<68>nes de caract<63>res pour remplacer des valeurs non constantes dans
|
|||
|
une requ<71>te ! Encore mieux, utilisez les param<61>tres nomm<6D>s dans les requ<71>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<73>mes de connexions livr<76>s,
|
|||
|
r<>fl<66>chissez <20> l'id<69>e de fournir votre propre impl<70>mentation de <literal>org.hibernate.connection.ConnectionProvider</literal>.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Pensez <20> utiliser les types utilisateurs.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Supposez que vous ayez une type Java, de telle biblioth<74>que, qui a besoin d'<27>tre persist<73> mais
|
|||
|
qui ne fournit pas les accesseurs n<>cessaires pour le mapper comme composant. Vous devriez
|
|||
|
impl<70>menter
|
|||
|
<literal>org.hibernate.UserType</literal>.Cette approche lib<69>re le code de l'application
|
|||
|
de l'impl<70>mentation des transformations vers / depuis les types Hibernate.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Utilisez du JDBC pur dans les goulets d'<27>tranglement.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Dans certaines parties critiques de votre syst<73>me d'un point de vue performance, quelques op<6F>rations
|
|||
|
peuvent tirer partie d'un appel JDBC natif.
|
|||
|
Mais attendez de <emphasis>savoir</emphasis>
|
|||
|
que c'est un goulet d'<27>tranglement. Ne supposez jamais qu'un appel JDBC sera forc<72>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<61>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 <20>tats persistants avec la base de donn<6E>es.
|
|||
|
Les performances seront affect<63>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<6F>rations men<65>es dans une transaction particuli<6C>re.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Dans une architecture <20> trois couches, pensez <20> utiliser <literal>saveOrUpdate()</literal>.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Quand vous utilisez une architecture <20> base de servlet / session bean, vous pourriez passer
|
|||
|
des objets charg<72>s dans le bean session vers et depuis la couche servlet / JSP. Utilisez
|
|||
|
une nouvelle session pour traiter chaque requ<71>te.
|
|||
|
Utilisez <literal>Session.merge()</literal> ou <literal>Session.saveOrUpdate()</literal> pour
|
|||
|
synchroniser les objets avec la base de donn<6E>es.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Dans une architecture <20> deux couches, pensez <20> utiliser la d<>connexion de session.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Les transactions de bases de donn<6E>es doivent <20>tre aussi courtes que possible
|
|||
|
pour une meilleure mont<6E>e en charge.Cependant, il est souvent n<>cessaire d'impl<70>menter
|
|||
|
de longues <emphasis>transactions applicatives</emphasis>, une simple unit<69> de travail du point de vue de
|
|||
|
l'utilisateur. Une transaction applicative
|
|||
|
peut s'<27>taler sur plusieurs cycles de requ<71>tes/r<>ponses du client.
|
|||
|
Il est commun d'utiliser des objets d<>tach<63>s pour impl<70>menter des transactions applicatives.
|
|||
|
Une alternative, extr<74>mement appropri<72>e dans une architecture <20> 2 couches, est de
|
|||
|
maintenir un seul contact de persistance ouvert (session) pour toute la dur<75>e de vie
|
|||
|
de la transaction applicative et simplement se d<>connecter de la connexion JDBC <20> la fin de chaque requ<71>te,
|
|||
|
et se reconnecter au d<>but de la requ<71>te suivante. Ne partagez jamais une seule
|
|||
|
session avec plus d'une transaction applicative, ou vous travaillerez avec des
|
|||
|
donn<6E>es p<>rim<69>es.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Consid<EFBFBD>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<6E>grit<69> des <20>tats persistants en m<>moire. En particulier,
|
|||
|
n'utilisez pas <literal>Session.load()</literal> pour d<>terminer si une instance avec un identifiant
|
|||
|
donn<6E> existe en base de donn<6E>es, utilisez <literal>Session.get()</literal> ou un requ<71>te.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Pr<EFBFBD>f<EFBFBD>rez le chargement tardif des associations.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Utilisez le chargement complet avec mod<6F>ration.
|
|||
|
Utilisez les proxies et les collections charg<72>es tardivement
|
|||
|
pour la plupart des associations vers des classes qui ne sont pas susceptibles
|
|||
|
d'<27>tre compl<70>tement retenues dans le cache de second niveau.
|
|||
|
Pour les assocations de classes en cache, o<> il y a une extr<74>mement
|
|||
|
forte probabilit<69> que l'<27>l<EFBFBD>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<72> pour un cas d'utilisation
|
|||
|
particulier, utilisez une requ<71>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<69>e pour <20>viter des probl<62>mes
|
|||
|
avec des donn<6E>es non rapatri<72>es.
|
|||
|
</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Hibernate lib<69>re les d<>veloppeurs de l'<27>criture fastidieuse des <emphasis>objets de transfert
|
|||
|
de donn<6E>es (NdT : Data Transfer Objects)</emphasis> (DTO). Dans une architecture EJB traditionnelle,
|
|||
|
les DTOs ont deux buts : premi<6D>rement, ils contournent le probl<62>me des "entity bean" qui ne sont pas
|
|||
|
s<>rialisables ; deuxi<78>mement, ils d<>finissent implicitement une phase d'assemblage o<> toutes les
|
|||
|
donn<6E>es utilis<69>es par la vue sont rapatri<72>es et organis<69>es dans les DTOs avant de retourner sous le
|
|||
|
contr<74>le de la couche de pr<70>sentation. Hibernate <20>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<70>sentation <20> propos de quelles donn<6E>es sont disponibles dans les objets d<>tach<63>s)
|
|||
|
<20> moins que vous soyez pr<70>par<61>s <20> garder le contexte de
|
|||
|
persistance (la session) ouvert <20> travers tout le processus de rendu de la vue.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Pensez <20> abstraite votre logique m<>tier d'Hibernate.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Cachez le m<>canisme d'acc<63>s aux donn<6E>es (Hibernate) derri<72>re une interface. Combinez les patterns
|
|||
|
<emphasis>DAO</emphasis> et <emphasis>Thread Local Session</emphasis>. Vous pouvez m<>me avoir quelques
|
|||
|
classes persist<73>es par du JDBC pur, associ<63>es <20> 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<63>es dans la table d'association.
|
|||
|
Dans ce cas, il est pr<70>f<EFBFBD>rable d'utiliser deux associations un-vers-plusieurs vers une classe
|
|||
|
de liaisons interm<72>diaire. En fait, nous pensons que la plupart des associations sont
|
|||
|
de type un-vers-plusieurs ou plusieurs-vers-un, vous devez <20>tre tr<74>s attentifs lorsque
|
|||
|
vous utilisez autre chose et vous demander si c'est vraiment n<>cessaire.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>Pr<EFBFBD>f<EFBFBD>rez les associations bidirectionnelles.</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Les associations unidirectionnelles sont plus difficiles <20> questionner.
|
|||
|
Dans une grande application, la plupart des associations devraient <20>tre navigables dans les deux directions dans les requ<71>tes.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
</variablelist>
|
|||
|
|
|||
|
</chapter>
|
|||
|
|