August 12, 2009

3 ways of integrating Hibernate and Spring

There are many ways to integrate Hibernate Data Access Objects (DAOs) with the Spring Framework. The Spring 2.5 documentation describes three possible solutions how Spring supports those DAOs. But which is the right way to go nowadays? Let's compare the three variants:



  1. Let your concrete DAO class extend HibernateDaoSupport. This base class has to be configured with a SessionFactory and gives access to Hibernate Sessions and a HibernateTemplate.
  2. Directly injecting a HibernateTemplate into your DAO class. You don't have to extend any framework class. The HibernateTemplate gives access to many general purpose dao methods. This is o.k. for many cases but accessing the hibernate session directly from the HibernateTemplate is verbose. You have to pass anonymous callbacks to get access to the session.
    On the other side the HibernateTemplate is handy when it comes to automatic handling of the hibernate session management (e.g. binding the session to the current Transaction) but as you'll see this is no longer needed in Hibernate 3. It also converts any Hibernate or SQL related Exception into a corresponding DataAccessException, which is very helpful.
  3. Directly injecting the Hibernate SessionFactory into your DAO class. Your DAO won't have dependancies on any class from the Spring Framework. Since Hibernate 3 is capable of binding the Session to a preset Context (e.g. Thread or Transaction) the HibernateTemplate is no longer needed.
So which of these variants should be preferred? If you use Hibernate 3 then you should stick with the third variant. Take a look at the Hibernate property current_session_context and Session#getCurrentSession() (see Hibernate documentation for details).
As you can read in the Javadoc of HibernateTemplate the Spring Team confirms this:
NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can also be coded in plain Hibernate style. Hence, for newly started projects, consider adopting the standard Hibernate3 style of coding data access objects instead, based on SessionFactory.getCurrentSession().
You may ask how you can get DataAccessExceptions with this variant? This is quite simple: just annotate your DAOs with @Repository and include this Spring Bean into you ApplicationContext:

5 comments:

Mike said...

If you go with option 3, to inject the Hibernate SessionFactory, like option 2, aren't you going to have a lot of boilerplate code?

I have always preferred to extend HibernateDaoSupport. Yes, this DAO will depend on Spring, but the the whole package will, and since we code to interfaces, if you needed an integration layer without Spring, you can simply reimplement your DAO interfaces into a new spring-free package. In the long run I think you have to write and manage a lot less code when you extend HibernateDaoSupport.

Thanks for the list of options. I think more comparison on the three options would be great.

Bryan said...

There shouldn't be any boilerplate at all (other than annotations). The session creation/rollback/commit/destruction is all handled by the transaction management. You should just be able to make hibernate queries on the session, and return the results.

Bryan said...

btw.. the comment submission form on this site is broke.. the iframe cuts off the bottom of the form in both safari and firefox on the mac.

Benjamin said...

Doh, looks good to me on Firefox 3.5 (Windows). Thanks for reporting this issue. I'll fix it later.

Benjamin said...

HibernateTemplate Javadoc:

NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can also be coded in plain Hibernate style. Hence, for newly started projects, consider adopting the standard Hibernate3 style of coding data access objects instead, based on SessionFactory.getCurrentSession().