This blog for Hibernate Generic DAO Project has been moved to WordPress http://hibernategenericdao.wordpress.com/. Bye bye Blogger!

Saturday, June 12, 2010

Configuring Hibernate Generic DAO with JPA

Version 0.5.0 introduced JPA to the "Hibernate" Generic DAO. Version 0.5.1 added a a JPAAnnotationMetadataUtil instance that makes simple non-Hibernate JPA configuration a bit simpler. Future versions willhopefully provide full out-of-the-box support for all JPA 2.0 providers. Until then, this post will explain how to configure Hibernate Generic DAO with JPA 1.0. (Although I hear some people have gotten it to work with 2.0 http://groups.google.com/group/java-generic-dao/browse_thread/thread/a3e792d989b55bb3)


There is an example configuration using Spring and Hibernate JPA in our SVN repo. You can download or browse the source online here: http://code.google.com/p/hibernate-generic-dao/source/browse/#svn/tags/0.5.1/sample/jpa-hibernate-maven%3Fstate%3Dclosed.


Let's get started with a diagram...


In the above diagram each box represents a singleton instance of a class (except EntityManager). These are all you need to know to set up the framework in your project. Let's take a look at the parts:


JPASearchProcessor: You will need one singleton instance of the JPASearchProcessor class for each persistence unit in your project. (Most projects have only one persistence unit and thus only one JPASearchProcessor.) The JPASearchProcessor has only one dependency, it must have an instance of MetadataUtil passed into its constructor.


MetadataUtil: Again you will need one singleton instance of MetadataUtil per persistence unit. The MetadataUtil is used to inform the framework of the structure and relationships in your data model.


While there is only one implementation of JPASearchProcessor, Hibernate Generic DAO ships with two build-in implementations of MetadataUtil. The first implementation that comes with the framework is HibernateMetadataUtil. HibernateMetadataUtil can only be used with Hibernate's JPA implementation. The second is JPAAnnotationMetadataUtil. This is a beta implementation that looks at the JPA annotations on Java classes to determine the data model. It should theoretically work with any JPA 1.0 implementation, but it has only been tested on some basic data models. If neither of these is sufficient for your needs, you can code your own implementation of the MetadataUtil interface. [In fact if someone wants to implement one using JPA 2.0's metadata model, that would be a major contribution to the project, allowing us to fully support any JPA 2.0 implementation out of the box.]


In our sample project in SVN we use Spring framework to create these two singletons and wire them together. In this case we are using the HibernateMetadataUtil class. This requires a reference to the Hibernate EntityManagerFactory which should be configured elsewhere with your Hibernate JPA configuration. Here is a snippet from the applicationContext.xml that show these two singletons.


<bean id="searchProcessor" class="com.trg.search.jpa.JPASearchProcessor">

<constructor-arg ref="metadataUtil" />

</bean>


<bean id="metadataUtil" class="com.trg.search.jpa.hibernate.HibernateMetadataUtil"

factory-method="getInstanceForEntityManagerFactory">

<constructor-arg ref="entityManagerFactory" />

</bean>


An alternative configuration that uses JPAAnnotationMetadataUtil would be as follows. JPAAnnotationMetadataUtil does not require any configuration options. It just looks for annotated classes on the classpath.


<bean id="searchProcessor" class="com.trg.search.jpa.JPASearchProcessor">

<constructor-arg ref="metadataUtil" />

</bean>


<bean id="metadataUtil" class="com.trg.search.jpa.JPAAnnotationMetadataUtil"/>



Diagram showing the dependencies for the two different MetadataUtil implementations. HibernateMetadataUtil requires a reference to the HibernateEntityManager. JPAAnnotationMetadataUtil stands alone.


Now that we have that set up, we turn to our individual DAOs. Each one requires two things, (1) a reference to the JPASearchProcessor singleton and (2) an EntityManager (not a singleton). You can decide how the DAO will get an EntityManager when it needs it by overriding the getEntityManager() method of GenericDAOImpl or GeneralDAOImpl. In the case of our example, we rely on Spring framework to inject the current EntityManager into our DAOs via the @PersistenceContext annotation on the setEntityManager() method. We are also having spring automatically set our JPASearchProcessor via an @Autowired annotation. In order to make both of these apply to all our DAOs, we have a base class that all of them extend. This is not necessary, but in this case it’s convenient. Here’s the code for the BaseDAO class:


@Repository

public class BaseDAO<T, ID extends Serializable> extends GenericDAOImpl<T, ID> {

@Override

@PersistenceContext

public void setEntityManager(EntityManager entityManager) {

super.setEntityManager(entityManager);

}

@Override

@Autowired

public void setSearchProcessor(JPASearchProcessor searchProcessor) {

super.setSearchProcessor(searchProcessor);

}

}


We took a similar strategy for the GeneralDAO (See DecoratedGeneralDAOImpl in the sample code).


So that’s basically all there is to know about configuring the framework for use with JPA. For other installation information start at this wiki page (http://code.google.com/p/hibernate-generic-dao/wiki/InstallationAndConfiguration).


Best of luck. Our forum is found at http://groups.google.com/group/java-generic-dao. And if anyone wants to contribute to features of this open source project or the JPA 2.0 updates, let me know.

2 comments:

  1. Hi, I'm studying JPA recently and I write the code in the EJB3 Container, the Code is:
    @Override
    @PersistenceContext(unitName = "Security")
    public void setEntityManager(EntityManager entityManager){
    System.out.println(entityManager);
    super.setEntityManager(entityManager);
    }
    And here the entityManager is null and I can't create or get data. But I don't know why the entityManager is null and Why I can't inject entityManager

    ReplyDelete
  2. @风中的索莉逖亚 Unfortunately, I don't know much about EJB3 configuration. I more often work with Spring Framework for bean management.

    ReplyDelete