Chapter 2. Setup and configuration

2.1. Setup

The EJB3 compatible Hibernate EntityManager is built on top of Hibernate core and Hibernate Annotations. You have to use compatible versions of each module. This version is known to work on Hibernate 3.1.1 and Hibernate Annotations 3.1beta8. The following libraries have to be in your classpath: hibernate3.jar, hibernate-annotations.jar, hibernate-entity-manager.jar and all needed third party libraries for each package.(incl. ejb-persistence.jar).

2.2. Configuration and bootstrapping

The configuration for entity managers both inside an application server and in a standalone application reside in a persistence archive. A persistence archive is a JAR file which must define a persistence.xml file that resides in the META-INF folder. All properly annotated classes included in the archive (ie having an @Entity annotation), all annotated packages and all Hibernate hbm.xml files included in the archive will be added to the persistence unit configuration, so by default, your persistence.xml will be quite minimalist:

<persistence>
   <persistence-unit>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>

Here's a more complete example of a persistence.xml file

<persistence>
   <persistence-unit name="manager1" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <mapping-file>ormap.xml</mapping-file>
      <jar-file>MyApp.jar</jar-file>
      <class>org.acme.Employee</class>
      <class>org.acme.Person</class>
      <class>org.acme.Address</class>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>
     
name

(attribute) Every entity manager must have a name. If no name is specified, the name of the archive file is used minus the .jar suffix.

transaction-type

(attribute) Transaction type used. Either JTA or RESOURCE_LOCAL (default JTA).

provider

The provider is a fully-qualified class name of the EJB Persistence provider. You do not have to define it if you don't work with several EJB3 implementations. This is needed when you are using multiple vendor implementations of EJB Persistence.

jta-data-source, non-jta-data-source

This is the JNDI name of where the javax.sql.DataSource is located. When running without a JNDI available Datasource, you must specify JDBC connections with Hibernate specific properties (see below).

mapping-file

The class element specifies a EJB3 compliant XML mapping file that you will map. This feature is currently not supported.

jar-file

The jar-file elements specifies a jar to analyse. All properly annotated classes, annotated packages and all hbm.xml files part of this jar file will be added to the persistence unit configuration. This element is mainly used in Java EE environment. Use of this one in Java SE should be considered as non portable, in this case a absolute url is needed.

exclude-unlisted-classes

Do not check the main jar file for annotated classes. Only explicit classes will be part of the persistence unit.

class

The class element specifies a fully qualified class name that you will map. By default all properly annotated classes and all hbm.xml files found inside the archive are added to the persistence unit configuration. You can add some external entity through the class element though. As an extension to the specification, you can add a package name in the <class> element (eg <class>org.hibernate.eg</class>).

properties

The properties element is used to specify vendor specific properties. This is where you will define your Hibernate specific configurations. This is also where you will have to specify JDBC connection information as well.

The EJB3 specification defines a bootstrap procedure to access the EntityManagerFactory and the EntityManager. The bootstrap class is javax.persistence.Persistence, e.g.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("manager1");
//or
Map configOverrides = new HashMap();
configOverrides.put("hibernate.hbm2ddl.auto", "create-drop");
EntityManagerFactory programmaticEmf =
    Persistence.createEntityManagerFactory("manager1", configOverrides);

The first version is equivalent to the second with an empty map. The map version is a set of overrides that will take precedence over any properties defined in your persistence.xml files. There are a couple of EJB3 properties usable in the map:

  • javax.persistence.provider to define the provider class used

  • javax.persistence.transactionType to define the transaction type used (either JTA or RESOURCE_LOCAL)

  • javax.persistence.jtaDataSource to define the JTA datasource name in JNDI

  • javax.persistence.nonJtaDataSource to define the non JTA datasource name in JNDI

When Persistence.createEntityManagerFactory() is called, the persistence implementation will search your classpath for any META-INF/persistence.xml files using the ClassLoader.getResource("META-INF/persistence.xml") method. From this list of resources, it will try to find an entity manager that matches the name you specify in the command line with what is specified in the persistence.xml file. If no persistence.xml with the correct name are found, a PersistenceException is raised. If there is only one persistence.xml in your classpath, you don't have to declare any entity manager factory name (however, if several files are found, a PersistenceException is raised).

EntityManagerFactory emf = Persistence.createEntityManagerFactory(null);

Apart from Hibernate system-level settings, all the properties available in Hibernate can be set in properties element of the persistence.xml file or as an override in the map you pass to createEntityManagerFactory(). Please refer to the Hibernate reference documentation for a complete listing. There are however a couple of properties available in the EJB3 provider only.

Table 2.1. Hibernate Entity Manager specific properties

Property nameDescription
hibernate.ejb.classcache.<classname>class cache strategy [comma cache region] of the class Default to no cache, and default region cache to fully.qualified.classname (eg. hibernate.ejb.classcache.com.acme.Cat read-write or hibernate.ejb.classcache.com.acme.Cat read-write, MyRegion).
hibernate.ejb.collectioncache.<collectionrole>collection cache strategy [comma cache region] of the class Default to no cache, and default region cache to fully.qualified.classname.role (eg. hibernate.ejb.classcache.com.acme.Cat read-write or hibernate.ejb.classcache.com.acme.Cat read-write, MyRegion).
hibernate.ejb.cfgfileXML configuration file to use to configure Hibernate (eg. /hibernate.cfg.xml).
hibernate.archive.autodetectionDetermine which element is auto discovered by Hibernate Entity Manager while parsing the .par archive. (default to class,hbm).
hibernate.ejb.interceptorAn optional Hibernate interceptor. This interceptor has to implement org.hibernate.Interceptor and have a no-arg constructor.
hibernate.ejb.naming_strategyAn optional naming strategy. The default naming strategy used is EJB3NamingStrategy. You also might want to consider the DefaultComponentSafeNamingStrategy.
hibernate.ejb.event.<eventtype>Event listener list for a given eventtype. The list of event listeners is a comma separated fully qualified class name list (eg. hibernate.ejb.event.pre-load com.acme.SecurityListener, com.acme.AuditListener)
hibernate.ejb.use_class_enhancerWhether or not use Application server class enhancement at deployment time (default to false)

Note that you can mix XML <class> declaration and hibernate.ejb.cfgfile usage in the same configuration. Be aware of the potential clashed. The properties set in persistence.xml will override the one in the defined hibernate.cfg.xml.

Here is a typical configuration in a J2SE environment

<persistence>
   <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
      <class>org.hibernate.ejb.test.Cat</class>
      <class>org.hibernate.ejb.test.Distributor</class>
      <class>org.hibernate.ejb.test.Item</class>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
         <property name="hibernate.connection.username" value="sa"/>
         <property name="hibernate.connection.password" value=""/>
         <property name="hibernate.connection.url" value="jdbc:hsqldb:."/>
         <property name="hibernate.max_fetch_depth" value="3"/>
       
         <!-- cache configuration -->
         <property name="hibernate.ejb.classcache.org.hibernate.ejb.test.Item" value="read-write"/>
         <property name="hibernate.ejb.collectioncache.org.hibernate.ejb.test.Item.distributors" value="read-write, RegionName"/>

         <!-- alternatively to <class> and <property> declarations, you can use a regular hibernate.cfg.xml file -->
         <!-- property name="hibernate.ejb.cfgfile" value="/org/hibernate/ejb/test/hibernate.cfg.xml"/ -->
      </properties>
   <persistence-unit>
</persistence>

To ease the programmatic configuration, Hibernate Entity Manager provide a proprietary API. This API is very similar to the Configuration API and share the same concepts: Ejb3Configuration. Refer to the JavaDoc and the Hibernate reference guide for more detailed informations on how to use it.

TODO: me more descriptive on some APIs like setDatasource()

Ejb3Configuration cfg = new Ejb3Configuration();
EntityManagerFactory emf = 
  cfg.configure("/mypath/hibernate.cfg.xml") //add a regular hibernate.cfg.xml
     .addProperties( properties ) //add some properties
     .setInterceptor( myInterceptorImpl ) // set an interceptor
     .addAnnotatedClass( MyAnnotatedClass.class ) //add a class to be mapped
     .addClass( NonAnnotatedClass.class ) //add an hbm.xml file using the Hibernate convention
     .addFile( "/mypath/MyOtherCLass.hbm.xml ) //add an hbm.xml file
     .createEntityManagerFactory(); //Create the entity manager factory

2.3. Event listeners

Hibernate Entity Manager needs to enhance Hibernate core to implements all the EJB3 semantics. It does that through the event listener system of Hibernate. Be careful when you use the event system yourself, you might override some of the EJB3 semantics. A safe way is to add your event listeners to the list given below.

Table 2.2. Hibernate Entity Manager default event listeners

EventListeners
flushorg.hibernate.ejb.event.EJB3FlushEventListener
auto-flushorg.hibernate.ejb.event.EJB3AutoFlushEventListener
deleteorg.hibernate.ejb.event.EJB3DeleteEventListener
flush-entityorg.hibernate.ejb.event.EJB3FlushEntityEventListener
mergeorg.hibernate.ejb.event.EJB3MergeEventListener
createorg.hibernate.ejb.event.EJB3PersistEventListener
create-onflushorg.hibernate.ejb.event.EJB3PersistOnFlushEventListener
saveorg.hibernate.ejb.event.EJB3SaveEventListener
save-updateorg.hibernate.ejb.event.EJB3SaveOrUpdateEventListener
pre-insertorg.hibernate.secure.JACCPreInsertEventListener, org.hibernate.valitator.event.ValidateEventListener
pre-insertorg.hibernate.secure.JACCPreUpdateEventListener, org.hibernate.valitator.event.ValidateEventListener
pre-deleteorg.hibernate.secure.JACCPreDeleteEventListener
pre-loadorg.hibernate.secure.JACCPreLoadEventListener
post-deleteorg.hibernate.ejb.event.EJB3PostDeleteEventListener
post-insertorg.hibernate.ejb.event.EJB3PostInsertEventListener
post-loadorg.hibernate.ejb.event.EJB3PostLoadEventListener
post-updateorg.hibernate.ejb.event.EJB3PostUpdateEventListener

Note that the JACC*EventListeners are removed if the security is not enabled.

You can configure the event listeners either through the properties (see Configuration and bootstrapping) or through the ejb3configuration.getEventListeners() API.

2.4. Obtaining an EntityManager in a J2SE environment

An entity manager factory should be considered as an immutable configuration holder, it is defined to point to a single datasource and to map a defined set of entities. This is the entry point to create and manage EntityManagers. The Persistence class is bootstrap class to create an entity manager factory.

// Use persistence.xml configuration
EntityManagerFactory emf = Peristence.createEntityManagerFactory("manager1")
EntityManager em = emf.createEntityManager(); // Retrieve a transactional-scoped entity manager
// Work with the EM
em.close();
...
emf.close(); //close at application end

An entity manager factory is typically create at application initialization time and closed at application end. It's creation is an expensive process. For those who are familiar with Hibernate, an entity manager factory is very much like a session factory. Actually, an entity manager factory is a wrapper on top of a session factory.

There are two kinds of entity managers. The transaction-scoped entity manager (default) create and destroy a persistence context for each transaction: in other words, the managed entities are detached once the transaction ends. The extended entity manager keep the same persistence context for the lifetime of the entity manager: in other words, the entities are still managed between two transactions. emf.createEntityManager() creates a transaction-scoped entity manager and emf.createEntityManager(PersistenceContextType.EXTENDED) creates an extended entity manager. You can see an entity manager as a small wrapper on top of an Hibernate session.

2.5. Various

Hibernate Entity Manager comes with Hibernate Validator configured out of the box. You don't have to override any event yourself. If you do not use Hibernate Validator annotations in your domain model, there will be no performance cost. For more information on Hibernate Validator, please refer to the Hibernate Annotations reference guide.