Architecture
Généralités
Voici une vue (très) haut niveau de l'architecture d'Hibernate :
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.
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 :
L'architecture la plus complète abstrait l'application des APIs JDBC/JTA
sous-jacentes et laisse Hibernate s'occuper des détails.
Voici quelques définitions des objets des diagrammes :
SessionFactory (org.hibernate.SessionFactory)
Un cache threadsafe (immuable) des mappings vers une (et une seule) base
de données. Une factory (fabrique) de Session et un client
de ConnectionProvider. 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.
Session (org.hibernate.Session)
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 Transaction. 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.
Objets et Collections persistants
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) Session. Dès que la Session
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).
Objets et collections transients
Instances de classes persistantes qui ne sont actuellement pas associées à
une Session. 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 Session fermée.
Transaction (org.hibernate.Transaction)
(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
Session peut fournir plusieurs Transactions
dans certains cas. Toutefois, la délimitation des transactions, via l'API d'Hibernate
ou par la Transaction sous-jacente, n'est jamais optionnelle!
ConnectionProvider (org.hibernate.connection.ConnectionProvider)
(Optionnel) Une fabrique de (pool de) connexions JDBC. Abstrait l'application
de la Datasource ou du DriverManager sous-jacent.
Non exposé à l'application, mais peut être étendu/implémenté par le développeur.
TransactionFactory (org.hibernate.TransactionFactory)
(Optionnel) Une fabrique d'instances de Transaction. Non
exposé à l'application, mais peut être étendu/implémenté par le développeur.
Interfaces d'extension
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.
Dans une architecture légère, l'application n'aura pas à utiliser les APIs
Transaction/TransactionFactory
et/ou n'utilisera pas les APIs ConnectionProvider
pour utiliser JTA ou JDBC.
Etats des instances
Une instance d'une classe persistante peut être dans l'un des trois états suivants,
définis par rapport à un contexte de persistance.
L'objet Session d'hibernate correspond à ce concept de
contexte de persistance :
passager (transient)
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)
persistant
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
garantit que l'identité persistante
est équivalente à l'identité Java (emplacement mémoire de l'objet)
détaché
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.
Intégration JMX
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 : org.hibernate.jmx.HibernateService.
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 :
Gestion de la session : Le cycle de vie de la Session
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 Session
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 Transaction d'Hibernate).
Vous appelez l'HibernateContext pour accéder à la Session.
Déploiement HAR : 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 SessionFactory
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.
Consultez le guide d'utilisation de JBoss AS pour plus d'informations sur ces options.
Les statistiques pendant l'exécution d'Hibernate (au runtime) sont une
autre fonctionnalité disponible en tant que service JMX. Voyez pour cela
.
Support JCA
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.
Sessions Contextuelles
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 ThreadLocal,
ainsi que sur des classes utilitaires comme HibernateUtil, ou utilisaient des
framework tiers (comme Spring ou Pico) qui fournissaient des sessions contextuelles basées sur
l'utilisation de proxy/interception.
A partir de la version 3.0.1, Hibernate a ajouté la méthode SessionFactory.getCurrentSession().
Initialement, cela demandait l'usage de transactions JTA, où la
transaction JTA 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 JTA TransactionManager ,
la plupart (sinon toutes) des applications devraient utiliser la gestion des transactions par JTA
qu'elles soient ou non déployées dans un conteneur J2EE. Par conséquent,
vous devriez toujours contextualiser vos sessions, si vous en avez besoin, via la méthode basée sur JTA.
Cependant, depuis la version 3.1, la logique derrière
SessionFactory.getCurrentSession() est désormais branchable.
A cette fin, une nouvelle interface d'extension (org.hibernate.context.CurrentSessionContext)
et un nouveau paramètre de configuration (hibernate.current_session_context_class)
ont été ajoutés pour permettre de configurer d'autres moyens de définir la portée et le contexte des
sessions courantes.
Allez voir les Javadocs de l'interface org.hibernate.context.CurrentSessionContext
pour une description détaillée de son contrat. Elle définit une seule méthode,
currentSession(), depuis laquelle l'implémentation est responsable
de traquer la session courante du contexte. Hibernate fournit deux implémentation
de cette interface.
org.hibernate.context.JTASessionContext - les sessions courantes sont
associées à une transaction JTA. La logique est la même que
l'ancienne approche basée sur JTA. Voir les javadocs pour les détails.
org.hibernate.context.ThreadLocalSessionContext - les sessions
courantes sont associées au thread d'exécution. Voir les javadocs pour les détails.
org.hibernate.context.ManagedSessionContext - les sessions
courantes sont traquées par l'exécution du thread. Toutefois, vous êtes responsable
de lier et délier une instance de Session avec les méthodes
statiques de cette classes, qui n'ouvre, ne flush ou ne ferme jamais de Session.
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 session-per-request.
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 Transaction 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 à pour plus d'informations
et des exemples de code.
Le paramètre de configuration hibernate.current_session_context_class
définit quelle implémentation de org.hibernate.context.CurrentSessionContext
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 org.hibernate.transaction.TransactionManagerLookup
est configuré, Hibernate utilisera le org.hibernate.context.JTASessionContext.
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".