Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

This article will show how to implement the DAO with Spring and Hibernate. For the core Hibernate configuration, check out the previous Hibernate 5 with Spring article.

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's now possible to make use of contextual sessionssessions managed directly by Hibernate and active throughout the scope of a transaction.

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

2.1. Exception Translation Without the HibernateTemplate

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 advise all @Repository beans with all the PersistenceExceptionTranslator found in the Spring context.

One thing to remember is that exception translation uses proxies. For Spring to be able to create proxies around the DAO classes, these must not be declared as 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 now highlights this aspect (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 that we can extend for each entity:

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

   @Autowired
   private SessionFactory sessionFactory;

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

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

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

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

   public void delete(T entity) {
      getCurrentSession().delete( entity );
   }
   public void deleteById(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 doesn't 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 constructor receives the Class of the entity as a parameter 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.

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.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
RainerOrKeiner
RainerOrKeiner
6 years ago

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… Read more »

Eugen Paraschiv
6 years ago
Reply to  RainerOrKeiner

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
RainerOrKeiner
6 years ago

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

Eugen Paraschiv
6 years ago
Reply to  RainerOrKeiner

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
RainerOrKeiner
6 years ago

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

Eugen Paraschiv
6 years ago
Reply to  RainerOrKeiner

Glad that solved your issue. Cheers,
Eugen.

Comments are closed on this article!