The DAO with Spring and Hibernate

I usually post about Persistence on Google+ - you can follow me there:

 

Table of Contents

1. Overview

This article will show how to implement the DAO with Spring and Hibernate. For the core Hibernate configuration, see the articles about Hibernate 3 and Hibernate 4 with Spring.

2. No More Spring Templates

Starting Spring 3.0 and Hibernate 3.0.1, the Spring HibernateTemplate is no longer necessary to manage the Hibernate Session. It is now possible to make use of contextual sessionssessions managed directly by Hibernate and active throughout the scope of a transaction.

As a consequence, it is now best practice to use the Hibernate API directly instead of the HibernateTemplate, which will effectively decouple the DAO layer implementation from Spring entirely.

2.1. Exception Translation without the HibernateTemplate – alive and well

Exception Translation was one of the responsibilities of HibernateTemplate – translating the low level Hibernate exceptions to higher level, generic Spring exceptions.

Without the template, this mechanism is still enabled and active for all the DAOs annotated with the @Repository annotation. Under the hood, this uses a Spring bean postprocessor that will advice all @Repository beans with all the PersistenceExceptionTranslator found in the Spring context.

One thing to remember is that exception translation is done through proxies; in order for Spring to be able to create proxies around the DAO classes, these must not be declared final.

2.2. Hibernate Session management without the Template

When Hibernate support for contextual sessions came out, the HibernateTemplate essentially became obsolete; in fact, the javadoc of the class has been updated with this advice (bold from the original):

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 {@link org.hibernate.SessionFactory#getCurrentSession()}.

3. The DAO

We’ll start with the base DAO - an abstract, parametrized DAO which supports the common generic operations and is meant to be extended for each entity:

public abstract class AbstractHibernateDAO< T extends Serializable >{
   private Class< T > clazz;

   @Autowired
   private SessionFactory sessionFactory;

   public void setClazz( final Class< T > clazzToSet ){
      clazz = clazzToSet;
   }

   public T findOne( final long id ){
      return (T) getCurrentSession().get( clazz, id );
   }
   public List< T > findAll(){
      return getCurrentSession()
       .createQuery( "from " + clazz.getName() ).list();
   }

   public void save( final T entity ){
      getCurrentSession().persist( entity );
   }

   public T update( final T entity ){
      return (T) getCurrentSession().merge( entity );
   }

   public void delete( final T entity ){
      getCurrentSession().delete( entity );
   }
   public void deleteById( final long id ){
      final T entity = findOne( id);
      delete( entity );
   }

   protected final Session getCurrentSession(){
      return sessionFactory.getCurrentSession();
   }
}

A few aspects are interesting here – as discussed, the abstract DAO does not extend any Spring template (such as HibernateTemplate). Instead, the Hibernate SessionFactory is injected directly in the DAO, and will have the role of the main Hibernate API, through the contextual Session it exposes:

this.sessionFactory.getCurrentSession();

Also, note that the Class of the entity is passed in the constructor to be used in the generic operations.

Now, let’s look at an example implementation of this DAO, for a Foo entity:

@Repository
public class FooDAO extends AbstractHibernateDAO< Foo > implements IFooDAO{

   public FooDAO(){
      setClazz(Foo.class );
   }
}

4. Conclusion

This article covered the configuration and implementation of the persistence layer with Hibernate and Spring 4, using both XML and Java based configuration.

The reasons to stop relying on templates for the DAO layer was discussed, as well as possible pitfalls of configuring Spring to manage transactions and the Hibernate Session. The final result is a lightweight, clean DAO implementation, with almost no compile-time reliance on Spring.

The implementation of this simple project can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Persistence on Google+ - you can follow me there:

>> GET THE EBOOKS <<
Get the eBooks and Learn to Build a Simple App
×
Build a Simple but Working App with Spring

, , ,

  • Chris Beams

    Eugen,

    Your readers will likely be interested to know that by upgrading to Hibernate 4 (release candidates available now; GA soon), and using Spring 3.1’s orm.hibernate4 package, they can take advantage of the new LocalSessionFactoryBuilder instead of using AnnotationSessionFactoryBean. The former provides a much nicer API for use within @Bean methods and avoids the need to deal with the FactoryBean’s getObject() method. You’ll notice that a HibernateExceptionTranslator is also present in that new package.

    Thanks for the posts, and keep them coming!

  • routinetap

    You can retrieve the persistence class this way:

    this.persistentClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];

    so there’s no need for setting the class on the constructor.

  • Alejandro Gomez

    Since you are talking about transactions you should use MySQL5InnoDBDialect in your example hibernate.properties. If the server default engine is MyISAM you won’t get transaction support.
    I know this is just reference code, but maybe someone wants to copy&paste it to try all this out.

  • Jean-Baptiste Nizet

    There is a good reason the Session.merge() method returns an entity: the passed detached entity state is copied to the attached version of the entity, and this attached entity is returned. If your update method ignores the returned value, it forces the caller to find it after, which is not very elegant. Moreover, I find it very confusing to use a different vocabulary than the standard one. Session has an update method, and your AbstractHibernateDAO also has one, but they don’t do the same thing. Same remark for save.

    • http://www.baeldung.com/ Eugen Paraschiv

      I fully agree on update – I changed the method signature in the example. For save however, the semantics of persist do not guarantee that an id is assigned right away, so nothing can be returned from that method. Thanks.

  • Ross Huggett

    Eugen, nice post. Particularly liked the use of generics there.

  • Martin

    Hi, sorry but i am a newbie at Hibernate and Spring and i am using your generic DAO implementation in order to start testing and playing with this stuff.
    I am a little confused with the Preconditions.whatever you are using in the generic DAO implementation. Is that an auxiliary class for checking if the entity about to be used is in the correct state before you actually do the merge, delete or whatever? In order to prevent exceptions? Or is it something different?
    Sorry for my very basic question, but i would like to fully understand what you have have so kindly expressed in such a clear way.

    • http://www.baeldung.com/ Eugen Paraschiv

      Preconditions is a Guava class – I cleaned up the example so that it doesn’t need external libraries.
      Thanks.

  • http://twitter.com/danwattDev Daniel Watt

    Great tutorial. We used this as a guide to get our Restful services up and running a few months ago.

    I have been noticing issues with our services when re-deploying to Tomcat, getting the dreaded out of permgen errors.

    The issue is deep inside of Spring + CGLIB, and has to do with Spring 3.1 + CGLib + no-xml config. one issue: https://jira.springsource.org/browse/SPR-9274

    The problem appears to be in PersistenceHibernateConfig. Two session factories are actually made – one for the @Bean for alertsSessionFactory, and a second for the call to alertsSessionFactory in transactionManager. The second one doesn’t get properly garbage collected on a webapp redeploy.

    Intead of calling alertsSessionFactory().getObject() inside of transactionManager(), pass in the AnnotationSessionFactoryBean. So, it would look like this:

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(AbstractSessionFactoryBean alertsSessionFactory){
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(alertsSessionFactory.getObject() );
    return txManager; }

    • http://www.baeldung.com/ Eugen Paraschiv

      Thanks for the suggestion – the configuration part of the article is now actually here (and updated).

  • Pingback: Java | Pearltrees()

  • RainerOrKeiner

    Nice Example so thanks a lot. I’m using it with Tomcat 7 and upgraded everything to Spring 4 and Hibernate 4.

    If I use the AbstractHibernateDao the Connection wont closed in any way. For example public final List findAll(). I will get all needed entities but the connection will not closed. If I modify the method like this:

    @Override
    @Transactional
    public final List findAll() {
    final Session session = this.getCurrentSession();
    final List list = session.createQuery(“from ” + clazz.getName())
    .list();
    session.close();
    return list;
    }

    the connection will be closed. I can’t find my problem. Is it a problem with the generic dao or is my configuration for Spring in trouble?

    • http://www.baeldung.com/ Eugen Paraschiv

      Hey Rainer – connection closing and releasing is a non trivial topic – and one I should write about in depth. In this case, the type of DAO (generic or specific) has nothing to do with it – it is definitely a configuration problem. I’d have to see your full persistence configuration to see what the issue is – so, if your project is on github (or similar) – please let me know and I’ll take a look. Otherwhise, try to set up Spring with Hibernate as described here. Cheers,
      Eugen.

      • RainerOrKeiner

        Hi Eugen,

        I exactly used your post
        http://www.baeldung.com/hibernate-4-spring . The only change is the
        usage of Spring 4 instead of Spring 3. I have posted my config in
        pastebin http://pastebin.com/hYg1CmrT .
        I also red the comments of
        http://www.baeldung.com/hibernate-4-spring . Someone already asked for
        closing the connection and it is said that Spring will close them. Maybe
        something has been change between Spring 3 and Spring 4 in that kind of
        process?

        Cheers,Rainer

        • http://www.baeldung.com/ Eugen Paraschiv

          Hey Reiner.
          There are a few possible reasons you may see this – most likely your services (or whatever else you’re using for your persistence layer) are not transactional in Spring. Try to rename your transaction manager to “transactionManager”.
          What this means is that the Hibernate transaction manager isn’t hooked up and won’t do any cleanup. The easiest way to check if this is the case is to add a breakpoint in the HibernateTransactionManager – processCommit. The method ends with a finally block which does cleanupAfterCompletion – which will actually close your session.
          Hope this helps. Cheers,
          Eugen.

          • RainerOrKeiner

            Hey Eugen,

            I think I was able to solve the problem. I forgot to add the transaction management. So I added “” to my hibernate config and added @Transactional to my dao classes.

            Cheers,
            Rainer

          • http://www.baeldung.com/ Eugen Paraschiv

            Glad that solved your issue. Cheers,
            Eugen.

Powered by WordPress. Designed by Woo Themes