Hibernate has the following integration points for J2EE infrastructure:
Container-managed datasources: Hibernate can use
JDBC connections managed by the container and provided through JNDI. Usually,
a JTA compatible TransactionManager
and a
ResourceManager
take care of transaction management (CMT),
esp. distributed transaction handling across several datasources. You may
of course also demarcate transaction boundaries programmatically (BMT) or
you might want to use the optional Hibernate Transaction
API for this to keep your code portable.
Automatic JNDI binding: Hibernate can bind its
SessionFactory
to JNDI after startup.
JTA Session binding: The Hibernate Session
may be automatically bound to the scope of JTA transactions. Simply
lookup the SessionFactory
from JNDI and get the current
Session
. Let Hibernate take care of flushing and closing the
Session
when your JTA transaction completes. Transaction
demarcation is either declarative (CMT) or programmatic (BMT/UserTransaction).
JMX deployment: If you have a JMX capable application server
(e.g. JBoss AS), you can chose to deploy Hibernate as a managed MBean. This saves
you the one line startup code to build your SessionFactory
from
a Configuration
. The container will startup your
HibernateService
, and ideally also take care of service
dependencies (Datasource has to be available before Hibernate starts, etc).
Depending on your environment, you might have to set the configuration option
hibernate.connection.aggressive_release
to true if your
application server shows "connection containment" exceptions.
The Hibernate Session
API is independent of any transaction
demarcation system in your architecture. If you let Hibernate use JDBC directly,
through a connection pool, you may begin and end your transactions by calling
the JDBC API. If you run in a J2EE application server, you might want to use bean-managed
transactions and call the JTA API and UserTransaction
when needed.
To keep your code portable between these two (and other) environments we recommend the optional
Hibernate Transaction
API, which wraps and hides the underlying system.
You have to specify a factory class for Transaction
instances by setting the
Hibernate configuration property hibernate.transaction.factory_class
.
There are three standard (built-in) choices:
org.hibernate.transaction.JDBCTransactionFactory
delegates to database (JDBC) transactions (default)
org.hibernate.transaction.JTATransactionFactory
delegates to container-managed transaction if an existing transaction is underway in this context (e.g. EJB session bean method), otherwise a new transaction is started and bean-managed transaction are used.
org.hibernate.transaction.CMTTransactionFactory
delegates to container-managed JTA transactions
You may also define your own transaction strategies (for a CORBA transaction service, for example).
Some features in Hibernate (i.e. the second level cache, Contextual Sessions with JTA, etc.)
require access to the JTA TransactionManager
in a managed environment.
In an application server you have to specify how Hibernate should obtain a reference to the
TransactionManager
, since J2EE does not standardize a single mechanism:
Table 3.10. JTA TransactionManagers
Transaction Factory | Application Server |
---|---|
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 |
A JNDI bound Hibernate SessionFactory
can simplify the lookup
of the factory and the creation of new Session
s. Note that this
is not related to a JNDI bound Datasource
, both simply use the
same registry!
If you wish to have the SessionFactory
bound to a JNDI namespace, specify
a name (eg. java:hibernate/SessionFactory
) using the property
hibernate.session_factory_name
. If this property is omitted, the
SessionFactory
will not be bound to JNDI. (This is especially useful in
environments with a read-only JNDI default implementation, e.g. Tomcat.)
When binding the SessionFactory
to JNDI, Hibernate will use the values of
hibernate.jndi.url
, hibernate.jndi.class
to instantiate
an initial context. If they are not specified, the default InitialContext
will be used.
Hibernate will automatically place the SessionFactory
in JNDI after
you call cfg.buildSessionFactory()
. This means you will at least have
this call in some startup code (or utility class) in your application, unless you use
JMX deployment with the HibernateService
(discussed later).
If you use a JNDI SessionFactory
, an EJB or any other class may
obtain the SessionFactory
using a JNDI lookup.
We recommend that you bind the SessionFactory
to JNDI in
a managed environment and use a static
singleton otherwise.
To shield your application code from these details, we also recommend to hide the
actual lookup code for a SessionFactory
in a helper class,
such as HibernateUtil.getSessionFactory()
. Note that such a
class is also a convenient way to startup Hibernatesee chapter 1.
The easiest way to handle Session
s and transactions is
Hibernates automatic "current" Session
management.
See the discussion of current sessions.
Using the "jta"
session context, if there is no Hibernate
Session
associated with the current JTA transaction, one will
be started and associated with that JTA transaction the first time you call
sessionFactory.getCurrentSession()
. The Session
s
retrieved via getCurrentSession()
in "jta"
context
will be set to automatically flush before the transaction completes, close
after the transaction completes, and aggressively release JDBC connections
after each statement. This allows the Session
s to
be managed by the life cycle of the JTA transaction to which it is associated,
keeping user code clean of such management concerns. Your code can either use
JTA programmatically through UserTransaction
, or (recommended
for portable code) use the Hibernate Transaction
API to set
transaction boundaries. If you run in an EJB container, declarative transaction
demarcation with CMT is preferred.
The line cfg.buildSessionFactory()
still has to be executed
somewhere to get a SessionFactory
into JNDI. You can do this
either in a static
initializer block (like the one in
HibernateUtil
) or you deploy Hibernate as a managed
service.
Hibernate is distributed with org.hibernate.jmx.HibernateService
for deployment on an application server with JMX capabilities, such as JBoss AS.
The actual deployment and configuration is vendor specific. Here is an example
jboss-service.xml
for 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>
This file is deployed in a directory called META-INF
and packaged
in a JAR file with the extension .sar
(service archive). You also need
to package Hibernate, its required third-party libraries, your compiled persistent classes,
as well as your mapping files in the same archive. Your enterprise beans (usually session
beans) may be kept in their own JAR file, but you may include this EJB JAR file in the
main service archive to get a single (hot-)deployable unit. Consult the JBoss AS
documentation for more information about JMX service and EJB deployment.