Hibernate possède les points suivants d'intégration à l'infrastructure J2EE :
Source de données gérée par le conteneur : Hibernate peut utiliser des connexions JDBC gérées par le conteneur et fournie par l'intermédiaire de JNDI. Souvent, un
TransactionManager
compatible JTA et un ResourceManager
s'occupent de la gestion des transactions (CMT). Ils sont particulièrement prévus pour pouvoir gérer des transactions distribuées
sur plusieurs sources de données. Vous pouvez bien sûr également définir vos limites de transaction dans votre programme (BMT)
ou vous pouvez sinon aussi utiliser l'API optionnelle Transaction
d'Hibernate qui vous garantira la portabilité de votre code entre plusieurs serveurs d'application.
Association JNDI automatique: Hibernate peut associer sa SessionFactory
à JNDI après le démarrage.
Association de la Session à JTA: La Session
Hibernate peut être associée automatiquement à une transaction JTA si vous utilisez les EJBs. Vous avez juste à récupérer
la SessionFactory
depuis JNDI et à récupérer la Session
courante. Hibernate s'occupe de vider et fermer la Session
lorsque le transaction JTA se termine. La démarcation des transactions se fait de manière déclarative dans les descripteurs
de déploiement.
Déploiement JMX :Si vous avez un serveur d'application compatible JMX (JBoss AS par exemple), vous pouvez choisir de déployer Hibernate en
temps que MBean géré par le serveur. Cela vous évite de coder la ligne de démarrage qui permet de construire la SessionFactory
depuis la Configuration
. Le conteneur va démarrer votre HibernateService
, et va idéalement s'occuper des dépendances entre les services (la source de données doit être disponible avant qu'Hibernate
ne démarre, etc).
En fonction de votre environnement, vous devrez peut être mettre l'option de configuration hibernate.connection.aggressive_release
à vrai si le serveur d'application affiche des exceptions de type "connection containment".
L'API de la Session
Hibernate est indépendante de tout système de démarcation des transactions qui peut être présent dans votre architecture.
Si vous laissez Hibernate utiliser l'API JDBC directement via un pool de connexion, vous devrez commencer et terminer vos
transactions en utilisant l'API JDBC. Si votre application tourne à l'intérieur d'un serveur d'application J2EE, vous voudrez
peut être utiliser les transactions gérées par les beans (BMT) et appeller l'API JTA et UserTransaction
lorsque cela est nécessaire.
Pour conserver votre code portable entre ces deux environnements (et d'autres éventuels) nous vous recommandons d'utiliser
l'API optionnelle Transaction
d'Hibernate, qui va encapsuler et masquer le système de transaction sous-jacent. Pour cela, vous devez préciser une classe
de fabrique d'instances de Transaction
en positionnant la propriété hibernate.transaction.factory_class
.
Il existe trois choix standards (fournis) :
net.sf.hibernate.transaction.JDBCTransactionFactory
délègue aux transactions de la base de données (JDBC). Valeur par défaut.
org.hibernate.transaction.JTATransactionFactory
délègue à CMT si une transaction existante est sous ce contexte (ex: méthode d'un EJB session), sinon une nouvelle transaction est entamée et une transaction gérée par le bean est utilisée.
org.hibernate.transaction.CMTTransactionFactory
délègue à aux transactions JTA gérées par le conteneur
Vous pouvez également définir votre propre stratégie transactionnelle (pour un service de transaction CORBA par exemple).
Certaines fonctionnalités d'Hibernate (i.e. le cache de second niveau, l'association automatique des Session à JTA, etc.)
nécessitent l'accès au TransactionManager
JTA dans un environnement "managé". Dans un serveur d'application, vous devez indiquer comment Hibernate peut obtenir une
référence vers le TransactionManager
, car J2EE ne fournit pas un seul mécanisme standard.
Tableau 3.10. TransactionManagers JTA
Fabrique de Transaction | Serveur d'application |
---|---|
org.hibernate.transaction.JBossTransactionManagerLookup |
JBoss |
org.hibernate.transaction.WeblogicTransactionManagerLookup |
Weblogic |
org.hibernate.transaction.WebSphereTransactionManagerLookup |
WebSphere |
org.hibernate.transaction.WebSphereExtendedJTATransactionLookup |
WebSphere 6 |
org.hibernate.transaction.OrionTransactionManagerLookup |
Orion |
org.hibernate.transaction.ResinTransactionManagerLookup |
Resin |
org.hibernate.transaction.JOTMTransactionManagerLookup |
JOTM |
org.hibernate.transaction.JOnASTransactionManagerLookup |
JOnAS |
org.hibernate.transaction.JRun4TransactionManagerLookup |
JRun4 |
org.hibernate.transaction.BESTransactionManagerLookup |
Borland ES |
Une SessionFactory
Hibernate associée au JNDI peut simplifier l'accès à la fabrique et donc la création de nouvelles Session
s. Notez que cela n'est pas lié avec les Datasource
associées au JNDI, elles utilisent juste le même registre.
Si vous désirez associer la SessionFactory
à un nom JNDI, spécifiez un nom (ex. java:hibernate/SessionFactory
) en utilisant la propriété hibernate.session_factory_name
. Si cette propriété est omise, la SessionFactory
ne sera pas associée au JNDI (c'est particulièrement pratique dans les environnements ayant une implémentation de JNDI en
lecture seule, comme c'est le cas pour Tomcat).
Lorsqu'il associe la SessionFactory
au JNDI, Hibernate utilisera les valeurs de hibernate.jndi.url
, hibernate.jndi.class
pour instancier un contexte d'initialisation. S'ils ne sont pas spécifiés, l'InitialContext
par défaut sera utilisé.
Hibernate va automatiquement placer la SessionFactory
dans JNDI après avoir appelé cfg.buildSessionFactory()
. Cela signifie que vous devez avoir cet appel dans un code de démarrage (ou dans une classe utilitaire) dans votre application
sauf si vous utilisez le déploiement JMX avec le service HibernateService
présenté plus tard dans ce document.
Si vous utilisez SessionFactory
JNDI, un EJB ou n'importe quelle autre classe peut obtenir la SessionFactory
en utilisant un lookup JNDI.
Nous recommandons que vous liiez la SessionFactory
à JNDI dans les environnements managés et que vous utilisiez un singleton static
si ce n'est pas le cas. Pour isoler votre application de ces détails, nous vous recommandons aussi de masquer le code de
lookup actuel pour une SessionFactory
dans une classe helper, comme HibernateUtil.getSessionFactory()
. Notez qu'une telle classe est aussi un moyen efficace de démarrer Hibernatevoir chapitre 1.
Le moyen le plus simple de gérer les Session
s et transactions est la gestion automatique de session "courante" offerte par Hibernate. Voir détail à Section 2.5, « Sessions Contextuelles ». En utilisant le contexte de session "jta"
session context, s'il n'y a pas de Session
associée à la transaction JTA courante, une session sera démarrée et associée à la transaction JTA courante la première fois
que vous appelez sessionFactory.getCurrentSession()
. Les Session
s obtenue via getCurrentSession()
dans une contexte "jta"
seront automatiquement flushées avant la validation de la transaction, fermées une fois la transaction complétée, et libéreront
les connexions JDBC de manière aggressive après chaque statement. Ceci permet aux Session
s d'être gérées par le cycle de vie de la transaction JTA à la quelle est sont associées, laissant le code de l'utilisateur
propre de ce type de gestion. Votre code peut soit utiliser JTA de manière programmatique via UserTransaction
, ou (ce qui est recommandé pour la portabilité du code) utiliser l'API Transaction
API pour marquer les limites. Si vous exécutez sous un conteneur EJB, la démarcation déclarative des transactions avec CMT
est recommandée.
La ligne cfg.buildSessionFactory()
doit toujours être exécutée quelque part pour avoir une SessionFactory
dans JNDI. Vous pouvez faire cela dans un bloc d'initialisation static
(comme celui qui se trouve dans la classe HibernateUtil
) ou vous pouvez déployer Hibernate en temps que service managé.
Hibernate est distribué avec org.hibernate.jmx.HibernateService
pour le déploiement sur un serveur d'application avec le support de JMX comme JBoss AS. Le déploiement et la configuration
sont spécifiques à chaque vendeur. Voici un fichier jboss-service.xml
d'exemple pour JBoss 4.0.x:
<?xml version="1.0"?> <server> <mbean code="org.hibernate.jmx.HibernateService" name="jboss.jca:service=HibernateFactory,name=HibernateFactory"> <!-- Required services --> <depends>jboss.jca:service=RARDeployer</depends> <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends> <!-- Bind the Hibernate service to JNDI --> <attribute name="JndiName">java:/hibernate/SessionFactory</attribute> <!-- Datasource settings --> <attribute name="Datasource">java:HsqlDS</attribute> <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute> <!-- Transaction integration --> <attribute name="TransactionStrategy"> org.hibernate.transaction.JTATransactionFactory</attribute> <attribute name="TransactionManagerLookupStrategy"> org.hibernate.transaction.JBossTransactionManagerLookup</attribute> <attribute name="FlushBeforeCompletionEnabled">true</attribute> <attribute name="AutoCloseSessionEnabled">true</attribute> <!-- Fetching options --> <attribute name="MaximumFetchDepth">5</attribute> <!-- Second-level caching --> <attribute name="SecondLevelCacheEnabled">true</attribute> <attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute> <attribute name="QueryCacheEnabled">true</attribute> <!-- Logging --> <attribute name="ShowSqlEnabled">true</attribute> <!-- Mapping files --> <attribute name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute> </mbean> </server>
Ce fichier est déployé dans un répertoire META-INF
et est packagé dans un fichier JAR avec l'extension .sar
(service archive). Vous devez également packager Hibernate, les librairies tierces requises, vos classes persistantes compilées
et vos fichiers de mapping dans la même archive. Vos beans entreprise (souvent des EJBs session) peuvent rester dans leur
propre fichier JAR mais vous pouvez inclure ce fichier JAR dans le jar principal du service pour avoir une seule unité déployable
à chaud. Vous pouvez consulter la documentation de JBoss AS pour plus d'information sur les services JMX et le déploiement
des EJBs.