JBoss-Hibernate Integration (Hibernate 2)
- Steve Ebersole, JBoss Inc
-
As of version 3.2.6{FOOTNOTE RED #1 1}, JBoss comes with built-in support for utilizing Hibernate within application code. This support
is provided by 3 high-level components:
Hibernate MBean - provides deployment, lifecycle, and management support around a Hibernate SessionFactory;
HAR Deployer - defines a Hibernate ARchive as a new deployable unit within JBoss AS;
Session Management - provides transparent management of Hibernate sessions.
-
Please note that versions integrating Hibernate2 into JBossAS are deprecated, in favor of those
inetgrating Hibernate3. See JBossHibernate3 for details on that integration.
-
Hibernate MBean
The Hibernate MBean is responsible for constructing a Hibernate SessionFactory and exposing it through JNDI. It also provides
JMX management capabilities around the deployed SessionFactory such that its configuration can be modified at runtime.
It exposes a number of configuration properties which affect its runtime behaviour. The more important of these include:
DatasourceName - the JNDI name of the datasource Hibernate should use;
Dialect - the RDBMS dialect;
SessionFactoryName - the JNDI name where the constructed SessionFactory should be bound;
CacheProviderClass - the Hibernate CacheProvider class to use for its second-level cache.
Check out the javadocs for org.jboss.hibernate.jmx.Hibernate for a complete list of the available configuration properties.
Notice that there is no option to specify the mapping documents to load. That is because the Hibernate MBean is meant to work
in conjuction with the HAR Deployer component and gets this information from there.
As an example of configuring the MBean, here is the configuration used in the unit tests:
<mbean code="org.jboss.hibernate.jmx.Hibernate" name="jboss.har:service=Hibernate"> <attribute name="DatasourceName">java:/DefaultDS</attribute> <attribute name="~SessionFactoryName">java:/hibernate/~SessionFactory</attribute> <attribute name="Dialect">net.sf.hibernate.dialect.HSQLDialect</attribute> <attribute name="CacheProviderClass">net.sf.hibernate.cache.HashtableCacheProvider</attribute> <attribute name="Hbm2ddlAuto">create-drop</attribute> </mbean>
<attribute name="ShowSqlEnabled">true</attribute> should be used to show the sql output, instead of the former
ShowSql
attribute
-
HAR Deployer
A Hibernate ARchive (or HAR) includes all the resources needed to deploy one or more Hibernate MBean instances. The archive must end
in a .har extension and contain a meta-inf/hibernate-service.xml which defines the Hibernate MBean(s) to deploy as well all the domain
classes and their mappings. The mappings can occur anywhere in the archive; the classes should maintain package structure. When a HAR
is processed by the HAR Deployer, a Hibernate MBean instance is created based on the HAR's meta-inf/hibernate-service.xml and the
contents of the har (the mappings are processed using Hibernate's Configuration.addJar() method).
A HAR can be deployed stand-alone or as part of an EAR. If included in an EAR, the EAR's meta-inf/jboss-app.xml must define the har
as a module as such:
<module> <har>har-file-name-relative-to-ear-root.har</har> </module>
Note the new <har/> module type used to denote the HAR subdeployment.
-
Session Management
All applications using Hibernate need to deal with the questions relating to the lifecycle of the Sessions they
obtain from the SessionFactory. When should the session be opened; how should components throughout the application
obtain the "current" session; how should flushing and closing of the session be handled?
The most common usage pattern for Hibernate in J2EE applications running within an application server is to use the
app server DataSource and TransactionManager capabilities. Typically a session is opened at the beginning of a
"request" and closed at the end of that "request", and in between the session is bound to the "current context" to be
accessible to application components.
The central piece of the Hibernate Session management component in JBoss is the org.jboss.hibernate.session.HibernateContext
class. HibernateContext exposes a static method named getSession() taking a String parameter which represents the jndi name
of a SessionFactory. If there is already a session bound to the "current context" for the given session factory name, then
that session is returned; otherwise, a new session is generated, bound to the "current context", and then returned.
So what constitutes the "current context" for a managed session? The transaction! This component uses the org.jboss.tm.TransactionLocal
class to associate a session with the current JTA transaction. The life of the session is then bound to that of the transaction. When
the session is bound, a Synchronization is registered with that transaction such that when the transaction is about to end the Hibernate
session can be flushed and closed.
There are two other pieces of functionality available through the HibernateContext class: the ability to handle "unmanaged sessions" and
ability for applications to manage the binding/unbinding of the Hibernate session themselves.
An unmanaged session is a session that is controlled by the HibernateContext, meaning it is not automatically flushed and closed. The session
is created on the same underlying jdbc connection and thus participates in the same JTA transaction. This is mostly useful for Hibernate
Interceptor implementations. The methods supporting this functionality are getUnmanagedSession() and releaseUnmanagedSession(). Check out
the javadocs for more info.
HibernateContext also exposes the methods bind(), unbind(), and prepareSession() to allow applications to manage the lifecycle of the Hibernate
session themselves. Say you have special requirements for obtaining a Hibernate session such as passing in your own JDBC connection or opening
a session with a session-level Interceptor (the MBean does support SessionFactory-level Interceptors). Then you can write the code which
generates a session and use these HibernateContext methods to expose this session to your application components; the idea being that no code
changes are needed in your components because they are still just using the HibernateContext.getSession() method. bind() and unbind() are
pretty self-explanatory; prepareSession() is used to perform the transaction Synchronization registration. Again, see the javadocs for more info.
The one caveat to note here is that due to the use of the TransactionLocal, the JTA transaction must be started prior to the session being
bound to the HibernateContext.
-
Why the need to pass the JNDI name to the HibernateContext.getSession() method? The HibernateContext class supports multiple simultaneously
deployed SessionFactories. You need to specify from which of those deployed SessionFactories you want the current session.
-
Bundling other versions of Hibernate2
-- TODO; should be as simple as bundling the version you want to use within the HAR and utilizing a loader-repository, but this needs
to be tested.
-
Hibernate2 vs. Hibernate3
See the switching doc regarding switching versions of
Hibernate used in the integration.
-
{FOOTNOTE RED #1 1} The session management code underwent a drastic change from its initial versions and this wiki page has been updated to reflect those
changes. However, the old page has been saved off at JBossHibernate-old
Comments