360 lines
20 KiB
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>
|
|
|