Chapter 13. Hibernate

Hibernate is a popular persistence engine that provides a simple, yet powerful, alternative to standard entity beans. Hibernate can run in almost any application server or even outside of an application server completely. Hibernate is very simple, but when running in JBoss, you can choose to deploy your application as a Hibernate archive, called a HAR file, and make Hibernate's simple usage even simpler. JBoss can manage your Hibernate session and other configuration details, allowing you to use Hibernate objects with minimal setup.

13.1. The Hibernate MBean

The Hibernate archive will instantiate and configure a Hibernate MBean (org.jboss.hibernate.jmx.Hibernate) that will be responsible for constructing a Hibernate SessionFactory and exposing it to your application through JNDI. In addition to this, the Hibernate MBean allows you to inspect and change the configuration of the SessionFactory at run time.

In its most basic configuration, the Hibernate MBean simply needs to know the database name and dialect as well as where to bind the SessionFactory in the JNDI tree. The following sample Hibernate MBean configuration illustrates a typical minimal Hibernate configuration.

<mbean code="org.jboss.hibernate.jmx.Hibernate" 
       name="jboss.har:service=Hibernate">
    <attribute name="DatasourceName">java:/DefaultDS</attribute>
    <attribute name="Dialect">net.sf.hibernate.dialect.HSQLDialect</attribute>
    <attribute name="SessionFactoryName">java:/hibernate/SessionFactory</attribute>

    <attribute name="CacheProviderClass">net.sf.hibernate.cache.HashtableCacheProvider</attribute>
</mbean>

The attributes shown here are:

  • DatasourceName: This is the JNDI name of the datasource Hibernate should use.

  • Dialect: This is the SQL dialect (database type) for the database being used. Any valid Hibernate dialect may be used. A few the more commonly used dialects are:

    • net.sf.hibernate.dialect.HSQLDialect

    • net.sf.hibernate.dialect.Oracle9Dialect

    • net.sf.hibernate.dialect.MySQLDialect

    • net.sf.hibernate.dialect.SQLServerDialect

    • net.sf.hibernate.dialect.FirebirdDialect

  • SessionFactoryName: This is the JNDI name where the constructed SessionFactory should be bound. Here we've chosen java:/hibernate/SessionFactory. If you are deploying multiple Hibernate applications in the server, make sure to choose a unique name.

This really is a small Hibernate configuration. There are many more configuration options available. We'll look at a few of the more useful options.

  • Hbm2ddlAuto: This option controls the automatic creation of tables for Hibernate objects. The valid values are create, create-drop and update.

  • DefaultSchema: This option sets a schema or tablespace name used to qualify unqualified tablenames in generated SQL.

  • ShowSqlEnabled: Setting this option to true enables logging of SQL to the console.

  • CacheProviderClass: This option sets the second level cache provider.

    • DeployedTreeCacheJndiName: This sets the the JNDI name of the JBossTreeCache instance to use if using the DeployedTreeCacheProvider.

  • SessionFactoryInterceptor: This sets the Interceptor on the configuration.

A full set of hibernate configuration properties is available on the MBean. Table 13.1, “The Hibernate MBean configuration properties and their corresponding property names” shows all the MBean properties that map to standard hibernate configuration properties. For more information on the hibernate configuration, see the Hibernate documentation or Hibernate in Action (Manning, 2004).

Table 13.1. The Hibernate MBean configuration properties and their corresponding property names

MBean PropertyStandard Hibernate Property
BatchVersionedDataEnabledhibernate.jdbc.batch_versioned_data
CacheProviderClasshibernate.cache.provider_class
CacheRegionPrefixhibernate.cache.region_prefix
DatasourceNamehibernate.connection.datasource
DefaultSchemahibernate.default_schema
Dialecthibernate.dialect
GeneratedKeysEnabledhibernate.jdbc.use_get_generated_keys
Hbm2ddlAutohibernate.hbm2ddl.auto
JdbcBatchSizehibernate.jdbc.batch_size
JdbcFetchSizehibernate.jdbc.fetch_size
JdbcScrollableResultSetEnabledhibernate.jdbc.use_scrollable_resultset
MaxFetchDepthhibernate.max_fetch_depth
MinimalPutsEnabledhibernate.cache.use_minimal_puts
Passwordhibernate.connection.password
QueryCacheEnabledhibernate.cache.use_query_cache
QuerySubstitutionshibernate.query.substitutions
ReflectionOptimizationEnabledhibernate.cglib.use_reflection_optimizer
SessionFactoryNamehibernate.session_factory_name
ShowSqlEnabledhibernate.show_sql
StreamsForBinaryEnabledhibernate.jdbc.use_streams_for_binary
Usernamehibernate.connection.username

13.2. Hibernate archives

JBoss provides a new, simplified way to package and deploy Hibernate applications. JBoss introduces the notion of a Hibernate Archive (HAR file). The HAR file allows you to provide Hibernate objects to your application code without performing any of the tedious manual configuration or setup code normally required.

Structurally a HAR file resembles a JBoss SAR file. The HAR file contains the Hibernate class files and a mapping files along with with a hibernate-service.xml deployment descriptor in the META-INF directory. We'll look first at the hibernate-service.xml file.

The hibernate-service.xml file is actually just a normal jboss-service.xml. The name is different, but the content is the same. The file should contain a definition for the Hibernate MBean (see Section 13.1, “The Hibernate MBean”) configured correctly for the needs of the Hibernate application being created. The following example shows a typical hibernate-service.xml file.

<server>
    <mbean code="org.jboss.hibernate.jmx.Hibernate" name="jboss.har:service=Hibernate"> 
        <attribute name="DatasourceName">java:/DefaultDS</attribute> 
        <attribute name="Dialect">net.sf.hibernate.dialect.HSQLDialect</attribute> 
        <attribute name="SessionFactoryName">java:/hibernate/CaveatEmptorSessionFactory</attribute>
        <attribute name="CacheProviderClass"> 
            net.sf.hibernate.cache.HashtableCacheProvider 
        </attribute> 
            
        <attribute name="Hbm2ddlAuto">create-drop</attribute>
        <attribute name="ShowSqlEnabled">true</attribute>
    </mbean>
</server> 

Notice that the hibernate-service.xml file does not contain a list of the classes Hibernate is to map the way a hibernate.cfg.xml would nor do you need to manually add the Hibernate mapping files to the configuration the way you would when using a hibernate.properties file. Instead the Hibernate deployer in JBoss scans the archive for .hbm.xml mapping files at deployment time and adds them to the configuration for you. Figure 13.1, “The structure of a typical HAR file” shows the layout of a typical HAR file.

The structure of a typical HAR file

Figure 13.1. The structure of a typical HAR file

The Hibernate deployer will create a configuration using all of the .hbm.xml files in the archive and bind a Hibernate SessionFactory into the JNDI tree at the appropriate location. The SessionFactory can then be used by any application in JBoss.

This example comes from the CaveatEmptor demo (http://caveatemptor.hibernate.org/). We've provided the CaveatEmptor code along with the examples in the book. To deploy the Hibernate portion of the demo as a HAR file, run the following command.

[examples]$ ant -Dchap=hibernate -Dex=1 run-example            
...
            [copy] Copying 1 file to /tmp/jboss-4.0.1/server/default/deploy
        

This creates and deploys the HAR file shown in Figure 13.1, “The structure of a typical HAR file”. If you look at the console log you will see the Hibernate classes located and deployed as well as the results of the schema generation.

13.3. Using the hibernate objects

When the Hibernate archive is deployed, the Hibernate objects are made available to other applications through the provided SessionFactory. There are several ways to use it.

Since the session factory is bound into JNDI, it is possible to simply look it up and manually create a Hibernate session. The following code does just that.

InitialContext ctx      = new InitialContext();
SessionFactory factory  = (SessionFactory)
                          ctx.lookup("java:/hibernate/CaveatEmptorSessionFactory");
Session        hsession = factory.openSession();

This requires manual management of the session the Hibernate transaction and may be useful for migrating existing Hibernate code into JBoss. However, in the context of a larger J2EE application, you'll likely want your Hibernate objects to take part in an existing JTA transaction. This would be the normal case if you wanted to access Hibernate objects in a session bean, for example.

JBoss provides the org.jboss.hibernate.session.HibernateContext class as the integration piece that does this. The getSession method returns a Hibernate session that is linked to the current JTA transaction. Naturally this requires that a JTA transaction exist prior to the call. The following code illustrates the use of getSession.

Session hsession = HibernateContext.getSession("java:/hibernate/CaveatEmptorSessionFactory");

When you get the Hibernate session in this manner, you don't need close the Hibernate session or manage a hibernate transaction. You can be sure that all access to the Hibernate session from the current transaction will see the same state, and you can know that your Hibernate access will be committed to the database or rolled back along with the larger JTA transaction.

13.4. Using a HAR file inside of an EAR file

Hibernate archives can be deployed as top level packages or can be deployed as a component of an EAR file. Since Hibernate archives are not a standard J2EE deployment type, we need to declare them in the jboss-app.xml file of an EAR file to use them that context. This is done with a module/har element as shown in the following example.

<!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN"
         "http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd">
<jboss-app>
   <module>
      <har>caveatemptor.har</har>
   </module>
</jboss-app>

With this, a Hibernate archive can be deployed along side a WAR or EAR file in any EAR file.

13.5. The HAR Deployer

The HAR deployer is defined in the jboss-hibernate.deployer file which by default is included in both the all and default configuration sets. The service definition for the HARDeployer MBean is shown below:

<server>
    <mbean code="org.jboss.hibernate.har.HARDeployer" name="jboss.har:service=HARDeployer">
        <attribute name="ValidateDTDs">false</attribute>
    </mbean>
</server>

It defines a single configuration property named ValidateDTDs, which denotes whether DTDs should be validated on deployment.