hibernate-orm/doc/reference/fr/modules/architecture.xml

360 lines
20 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<chapter id="architecture">
<title>Architecture</title>
<sect1 id="architecture-overview" revision="1">
<title>Généralités</title>
<para>
Voici une vue (très) haut niveau de l'architecture d'Hibernate :
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/overview.svg" format="SVG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="../shared/images/overview.gif" format="GIF" align="center"/>
</imageobject>
</mediaobject>
<para>
Ce diagramme montre Hibernate utilisant une base de données et des données
de configuration pour fournir un service de persistance (et des objets
persistants) à l'application.
</para>
<para>
Nous aimerions décrire une vue plus détaillée de l'architecture. Malheureusement,
Hibernate est flexible et supporte différentes approches. Nous allons en
montrer les deux extrêmes. L'architecture légère laisse l'application fournir
ses propres connexions JDBC et gérer ses propres transactions. Cette approche
utilise le minimum des APIs Hibernate :
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/lite.svg" format="SVG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="../shared/images/lite.gif" format="GIF" align="center"/>
</imageobject>
</mediaobject>
<para>
L'architecture la plus complète abstrait l'application des APIs JDBC/JTA
sous-jacentes et laisse Hibernate s'occuper des détails.
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/full_cream.svg" format="SVG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="../shared/images/full_cream.gif" format="GIF" align="center"/>
</imageobject>
</mediaobject>
<para>
Voici quelques définitions des objets des diagrammes :
<variablelist spacing="compact">
<varlistentry>
<term>SessionFactory (<literal>org.hibernate.SessionFactory</literal>)</term>
<listitem>
<para>
Un cache threadsafe (immuable) des mappings vers une (et une seule) base
de données. Une factory (fabrique) de <literal>Session</literal> et un client
de <literal>ConnectionProvider</literal>. Peut contenir un cache optionnel de
données (de second niveau) qui est réutilisable entre les différentes transactions
que cela soit au sein du même processus (JVLM) ou par plusieurs n½uds d'un cluster.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Session (<literal>org.hibernate.Session</literal>)</term>
<listitem>
<para>
Un objet mono-threadé, à durée de vie courte, qui représente une conversation
entre l'application et l'entrepôt de persistance. Encapsule une connexion JDBC.
Factory (fabrique) des objets <literal>Transaction</literal>. Contient un cache
(de premier niveau) des objets persistants, ce cache est obligatoire. Il est
utilisé lors de la navigation dans le graphe d'objets ou lors de la récupération
d'objets par leur identifiant.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Objets et Collections persistants</term>
<listitem>
<para>
Objets mono-threadés à vie courte contenant l'état de persistance
et la fonction métier. Ceux-ci sont en général les objets de type JavaBean
(ou POJOs) ; la seule particularité est qu'ils sont associés avec une (et
une seule) <literal>Session</literal>. Dès que la <literal>Session</literal>
est fermée, ils seront détachés et libres d'être utilisés par n'importe laquelle
des couches de l'application (ie. de et vers la présentation en tant que Data
Transfer Objects - DTO : objet de transfert de données).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Objets et collections transients</term>
<listitem>
<para>
Instances de classes persistantes qui ne sont actuellement pas associées à
une <literal>Session</literal>. Elles ont pu être instanciées par l'application
et ne pas avoir (encore) été persistées ou elle ont pu être instanciées par
une <literal>Session</literal> fermée.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Transaction (<literal>org.hibernate.Transaction</literal>)</term>
<listitem>
<para>
(Optionnel) Un objet mono-threadé à vie courte utilisé par l'application
pour définir une unité de travail atomique. Abstrait l'application des
transactions sous-jacentes qu'elles soient JDBC, JTA ou CORBA. Une
<literal>Session</literal> peut fournir plusieurs <literal>Transaction</literal>s
dans certains cas. Toutefois, la délimitation des transactions, via l'API d'Hibernate
ou par la <literal>Transaction</literal> sous-jacente, n'est jamais optionnelle!
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ConnectionProvider (<literal>org.hibernate.connection.ConnectionProvider</literal>)</term>
<listitem>
<para>
(Optionnel) Une fabrique de (pool de) connexions JDBC. Abstrait l'application
de la <literal>Datasource</literal> ou du <literal>DriverManager</literal> sous-jacent.
Non exposé à l'application, mais peut être étendu/implémenté par le développeur.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>TransactionFactory (<literal>org.hibernate.TransactionFactory</literal>)</term>
<listitem>
<para>
(Optionnel) Une fabrique d'instances de <literal>Transaction</literal>. Non
exposé à l'application, mais peut être étendu/implémenté par le développeur.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>Interfaces d'extension</emphasis></term>
<listitem>
<para>
Hibernate fournit de nombreuses interfaces d'extensions optionnelles que
vous pouvez implémenter pour personnaliser le comportement de votre couche de persistance.
Reportez vous à la documentation de l'API pour plus de détails.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Dans une architecture légère, l'application n'aura pas à utiliser les APIs
<literal>Transaction</literal>/<literal>TransactionFactory</literal>
et/ou n'utilisera pas les APIs <literal>ConnectionProvider</literal>
pour utiliser JTA ou JDBC.
</para>
</sect1>
<sect1 id="architecture-states" revision="1">
<title>Etats des instances</title>
<para>
Une instance d'une classe persistante peut être dans l'un des trois états suivants,
définis par rapport à un <emphasis>contexte de persistance</emphasis>.
L'objet <literal>Session</literal> d'hibernate correspond à ce concept de
contexte de persistance :
</para>
<variablelist spacing="compact">
<varlistentry>
<term>passager (transient)</term>
<listitem>
<para>
L'instance n'est pas et n'a jamais été associée à un contexte
de persistance. Elle ne possède pas d'identité persistante (valeur de clé primaire)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>persistant</term>
<listitem>
<para>
L'instance est associée au contexte de persistance.
Elle possède une identité persistante (valeur de clé primaire)
et, peut-être, un enregistrement correspondant dans la base.
Pour un contexte de persistance particulier, Hibernate
<emphasis>garantit</emphasis> que l'identité persistante
est équivalente à l'identité Java (emplacement mémoire de l'objet)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>détaché</term>
<listitem>
<para>
L'instance a été associée au contexte de persistance mais ce
contexte a été fermé, ou l'instance a été sérialisée vers un
autre processus. Elle possède une identité persistante et
peut-être un enregistrement correspondant dans la base.
Pour des instances détachées, Hibernate ne donne aucune
garantie sur la relation entre l'identité persistante et
l'identité Java.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1 id="architecture-jmx" revision="1">
<title>Intégration JMX</title>
<para>
JMX est le standard J2EE de gestion des composants Java.
Hibernate peut être géré via un service JMX standard. Nous fournissons une implémentation
d'un MBean dans la distribution : <literal>org.hibernate.jmx.HibernateService</literal>.
</para>
<para>
Pour avoir un exemple sur la manière de déployer Hibernate en tant que service JMX dans le
serveur d'application JBoss Application Server, référez vous au guide utilisateur JBoss (JBoss User Guide).
Si vous déployez Hibernate via JMX sur JBoss AS, vous aurez également les bénéfices suivants :
</para>
<itemizedlist>
<listitem>
<para>
<emphasis>Gestion de la session :</emphasis> Le cycle de vie de la <literal>Session</literal>
Hibernate peut être automatiquement limitée à la portée d'une transaction JTA.
Cela signifie que vous n'avez plus besoin d'ouvrir et de fermer la <literal>Session</literal>
manuellement, cela devient le travail de l'intercepteur EJB de JBoss. Vous n'avez
pas non plus à vous occuper des démarcations des transactions dans votre code (sauf
si vous voulez écrire une couche de persistance qui soit portable, dans ce cas vous
pouvez utiliser l'API optionnelle <literal>Transaction</literal> d'Hibernate).
Vous appelez l'<literal>HibernateContext</literal> pour accéder à la <literal>Session</literal>.
</para>
</listitem>
<listitem>
<para>
<emphasis>Déploiement HAR :</emphasis> Habituellement vous déployez le service JMX
Hibernate en utilisant le descripteur de déploiement de JBoss (dans un fichier EAR et/ou un SAR),
il supporte toutes les options de configuration usuelles d'une <literal>SessionFactory</literal>
Hibernate. Cependant, vous devez toujours nommer tous vos fichiers de mapping dans le
descripteur de déploiement. Si vous décidez d'utiliser le déploiement optionnel sous forme
de HAR, JBoss détectera automatiquement tous vos fichiers de mapping dans votre fichier HAR.
</para>
</listitem>
</itemizedlist>
<para>
Consultez le guide d'utilisation de JBoss AS pour plus d'informations sur ces options.
</para>
<para>
Les statistiques pendant l'exécution d'Hibernate (au runtime) sont une
autre fonctionnalité disponible en tant que service JMX. Voyez pour cela
<xref linkend="configuration-optional-statistics"/>.
</para>
</sect1>
<sect1 id="architecture-jca" revision="1">
<title>Support JCA</title>
<para>
Hibernate peut aussi être configuré en tant que connecteur JCA. Référez-vous au site
web pour de plus amples détails. Il est important de noter que le support JCA d'Hibernate
est encore considéré comme expérimental.
</para>
</sect1>
<sect1 id="architecture-current-session" revision="2">
<title>Sessions Contextuelles</title>
<para>
Certaines applications utilisant Hibernate ont besoin d'une sorte de session "contextuelle", où
une session est liée à la portée d'un contexte particulier. Cependant, les applications ne définissent
pas toutes la notion de contexte de la même manière, et différents contextes définissent différentes
portées à la notion de "courant". Les applications à base d'Hibernate, versions précédentes à la 3.0
utilisaient généralement un principe maison de sessions contextuelles basées sur le <literal>ThreadLocal</literal>,
ainsi que sur des classes utilitaires comme <literal>HibernateUtil</literal>, ou utilisaient des
framework tiers (comme Spring ou Pico) qui fournissaient des sessions contextuelles basées sur
l'utilisation de proxy/interception.
</para>
<para>
A partir de la version 3.0.1, Hibernate a ajouté la méthode <literal>SessionFactory.getCurrentSession()</literal>.
Initialement, cela demandait l'usage de transactions <literal>JTA</literal>, où la
transaction <literal>JTA</literal> définissait la portée et le contexte de la session courante.
L'équipe Hibernate pense que, étant donnée la maturité des implémentations de <literal>JTA TransactionManager</literal> ,
la plupart (sinon toutes) des applications devraient utiliser la gestion des transactions par <literal>JTA</literal>
qu'elles soient ou non déployées dans un conteneur <literal>J2EE</literal>. Par conséquent,
vous devriez toujours contextualiser vos sessions, si vous en avez besoin, via la méthode basée sur JTA.
</para>
<para>
Cependant, depuis la version 3.1, la logique derrière
<literal>SessionFactory.getCurrentSession()</literal> est désormais branchable.
A cette fin, une nouvelle interface d'extension (<literal>org.hibernate.context.CurrentSessionContext</literal>)
et un nouveau paramètre de configuration (<literal>hibernate.current_session_context_class</literal>)
ont été ajoutés pour permettre de configurer d'autres moyens de définir la portée et le contexte des
sessions courantes.
</para>
<para>
Allez voir les Javadocs de l'interface <literal>org.hibernate.context.CurrentSessionContext</literal>
pour une description détaillée de son contrat. Elle définit une seule méthode,
<literal>currentSession()</literal>, depuis laquelle l'implémentation est responsable
de traquer la session courante du contexte. Hibernate fournit deux implémentation
de cette interface.
</para>
<itemizedlist>
<listitem>
<para>
<literal>org.hibernate.context.JTASessionContext</literal> - les sessions courantes sont
associées à une transaction <literal>JTA</literal>. La logique est la même que
l'ancienne approche basée sur JTA. Voir les javadocs pour les détails.
</para>
</listitem>
<listitem>
<para>
<literal>org.hibernate.context.ThreadLocalSessionContext</literal> - les sessions
courantes sont associées au thread d'exécution. Voir les javadocs pour les détails.
</para>
</listitem>
<listitem>
<para>
<literal>org.hibernate.context.ManagedSessionContext</literal> - les sessions
courantes sont traquées par l'exécution du thread. Toutefois, vous êtes responsable
de lier et délier une instance de <literal>Session</literal> avec les méthodes
statiques de cette classes, qui n'ouvre, ne flush ou ne ferme jamais de <literal>Session</literal>.
</para>
</listitem>
</itemizedlist>
<para>
Les deux implémentations fournissent un modèle de programmation de type "une session - une transaction
à la base de données", aussi connu sous le nom de <emphasis>session-per-request</emphasis>.
Le début et la fin d'une session Hibernate sont définis par la durée d'une transaction de base de données.
Si vous utilisez une démarcation programmatique de la transaction (par exemple sous J2SE ou JTA/UserTransaction/BMT),
nous vous conseillons d'utiliser l'API Hibernate <literal>Transaction</literal> pour masquer le système
de transaction utilisé. Si vous exécutez sous un conteneur EJB qui supporte CMT, vous n'avez besoin d'aucune
opérations de démarcations de session ou transaction dans votre code puisque tout
est géré de manière déclarative. Référez vous à <xref linkend="transactions"/> pour plus d'informations
et des exemples de code.
</para>
<para>
Le paramètre de configuration <literal>hibernate.current_session_context_class</literal>
définit quelle implémentation de <literal>org.hibernate.context.CurrentSessionContext</literal>
doit être utilisée. Notez que pour assurer la compatibilité avec les versions précédentes, si
ce paramètre n'est pas défini mais qu'un <literal>org.hibernate.transaction.TransactionManagerLookup</literal>
est configuré, Hibernate utilisera le <literal>org.hibernate.context.JTASessionContext</literal>.
La valeur de ce paramètre devrait juste nommer la classe d'implémentation à utiliser,
pour les deux implémentations fournies, il y a cependant deux alias correspondant: "jta" et "thread".
</para>
</sect1>
</chapter>