I’m a software engineer with a passion for REST, TDD and clean code, Web Security and Data Mining. Baeldung is about all of these and more. Eugen is a DZone MVB and is not an employee of DZone and has posted 20 posts at DZone. You can read more from them at their website. View Full User Profile

Simplifying the Data Access Layer with Spring and Java Generics

01.05.2012
| 9074 views |
  • submit to reddit

1. Overview

This is the second of a series of articles about Persistence with Spring. The previous article discussed setting up the persistence layer with Spring 3.1 and Hibernate, without using templates. This article will focus on simplifying the Data Access Layer by using a single, generified DAO, which will result in elegant data access, with no unnecessary clutter. Yes, in Java.

The Persistence with Spring series:

2. The DAO mess

Most production codebases have some kind of DAO layer. Usually the implementation ranges from a raw class with no inheritance to some kind of generified class, but one thing is consistent – there is always more then one. Most likely, there are as many DAOs as there are entities in the system. Also, depending on the level of generics involved, the actual implementations can vary from heavily duplicated code to almost empty, with the bulk of the logic grouped in an abstract class.

2.1. A Generic DAO

Instead of having multiple implementations – one for each entity in the system – a single parametrized DAO can be used in such a way that it still takes full advantage of the type safety provided by generics.

Two implementations of this concept are presented next, one for a Hibernate centric persistence layer and the other focusing on JPA. These implementation are by no means complete – only some data access methods are included, but they can be easily be made more thorough.

2.2. The Abstract Hibernate DAO

public abstract class AbstractHibernateDAO< T extends Serializable > {
   
   private Class< T > clazz;
   
   @Autowired
   SessionFactory sessionFactory;
   
   public void setClazz( Class< T > clazzToSet ){
      this.clazz = clazzToSet;
   }
   
   public T findOne( Long id ){
      return (T) this.getCurrentSession().get( this.clazz, id );
   }
   public List< T > findAll(){
      return this.getCurrentSession()
       .createQuery( "from " + this.clazz.getName() ).list();
   }
   
   public void save( T entity ){
      this.getCurrentSession().persist( entity );
   }
   
   public void update( T entity ){
      this.getCurrentSession().merge( entity );
   }
   
   public void delete( T entity ){
      this.getCurrentSession().delete( entity );
   }
   public void deleteById( Long entityId ){
      T entity = this.getById( entityId );
      
      this.delete( entity );
   }
   
   protected Session getCurrentSession(){
      return this.sessionFactory.getCurrentSession();
   }
}

The DAO uses the Hibernate API directly, without relying on any Spring templates (such as HibernateTemplate). Using of templates, as well as management of the SessionFactory which is autowired in the DAO were covered in the previous post of the series.

2.3. The Abstract JPA DAO

public abstract class AbstractJpaDAO< T extends Serializable > {
   
   private Class< T > clazz;
   
   @PersistenceContext
   EntityManager entityManager;
   
   public void setClazz( Class< T > clazzToSet ){
      this.clazz = clazzToSet;
   }
   
   public T findOne( Long id ){
      return this.entityManager.find( this.clazz, id );
   }
   public List< T > findAll(){
      return this.entityManager.createQuery( "from " + this.clazz.getName() )
       .getResultList();
   }
   
   public void save( T entity ){
      this.entityManager.persist( entity );
   }
   
   public void update( T entity ){
      this.entityManager.merge( entity );
   }
   
   public void delete( T entity ){
      this.entityManager.remove( entity );
   }
   public void deleteById( Long entityId ){
      T entity = this.getById( entityId );
      
      this.delete( entity );
   }
}

Similar to the Hibernate DAO implementation, the Java Persistence API is used here directly, again not relying on the now deprecated Spring JpaTemplate.

2.4. The Generic DAO

Now, the actual implementation of the generic DAO is as simple as it can be – it contains no logic. Its only purpose is to be injected by the Spring container in a service layer (or in whatever other type of client of the Data Access Layer):

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericJpaDAO< T extends Serializable >
 extends AbstractJpaDAO< T > implements IGenericDAO< T >{
   //
}

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericHibernateDAO< T extends Serializable >
 extends AbstractHibernateDAO< T > implements IGenericDAO< T >{
   //
}

First, note that the generic implementation is itself parametrized – allowing the client to choose the correct parameter in a case by case basis. This will mean that the clients gets all the benefits of type safety without needing to create multiple artifacts for each entity.

Second, notice the prototype scope of these generic DAO implementation. Using this scope means that the Spring container will create a new instance of the DAO each time it is requested (including on autowiring). That will allow a service to use multiple DAOs with different parameters for different entities, as needed.

The reason this scope is so important is due to the way Spring initializes beans in the container. Leaving the generic DAO without a scope would mean using the default singleton scope, which would lead to a single instance of the DAO living in the container. That would obviously be majorly restrictive for any kind of more complex scenario.

3. The Service

There is now a single DAO to be injected by Spring; also, the Class needs to be specified:

@Service
class FooService implements IFooService{
   
   IGenericDAO< Foo > dao;
   
   @Autowired
   public void setDao( IGenericDAO< Foo > daoToSet ){
      this.dao = daoToSet;
      this.dao.setClazz( Foo.class );
   }
   
   // ...
   
}

Spring autowires the new DAO insteince using setter injection so that the implementation can be customized with the Class object. After this point, the DAO is fully parametrized and ready to be used by the service.

4. Conclusion

This article discussed the simplification of the Data Access Layer by providing a single, reusable implementation of a generic DAO. This implementation was presented in both a Hibernate and a JPA based environment. The result is a streamlined persistence layer, with no unnecessary clutter.

For a step by step introduction about setting up the Spring context using Java based configuration and the basic Maven pom for the project, see this article. The next article of the Persistence with Spring series will focus on setting up the DAL layer with Spring 3.1 and JPA. In the meantime, you can check out the full implementation in the github project.

If you read this far, you should follow me on twitter here.

Published at DZone with permission of Eugen Paraschiv, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Vitaliy Morarian replied on Thu, 2012/01/05 - 10:53am

Why your DAO's are with prototype scope?

Vitaliy Morarian replied on Thu, 2012/01/05 - 10:53am

Why your DAO's are with prototype scope?

Eugen Paraschiv replied on Thu, 2012/01/05 - 1:59pm in response to: Vitaliy Morarian

In short, the PROTOTYPE scope is needed because otherwhise there would be a single DAO instance (singleton) in the Spring container, not one for each Entity class. For a in depth discussion on this (PROS and CONS), see the comment section of the article.

Thanks. 

Eugen. 

Lutz replied on Fri, 2012/01/06 - 8:33am in response to: Eugen Paraschiv

have you considered injecting the class parameter into you dao definitions? you could do something like (sry for using xml style config, dont know the fancy annotations syntax out of my head.)

<bean name="fooDao" class="dao.AbstractHibernateDAO" >
<parameter name="clazz" value="domain.Foo" />
</bean>

this way you would only ever have one DAO instance per domain class, and can inject the appropriate DAOs in your services.

Caesar Ralf Fra... replied on Fri, 2012/01/06 - 12:08pm

You could infer the entity class by retrieving the Generic type in the constructor. Like the code below:

private static final ENTITY_PARAM_IDX = 0;

public AbstractHibernateDao() {
    setClazz((Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[ENTITY_PARAM_IDX]));

Eugen Paraschiv replied on Sat, 2012/01/07 - 8:48am in response to: Lutz

I prefer making good use of Spring 3 annotations, which means that the DAOs are not defined in XML at all. That being said, the way the class is injected seems to be generating a lot of comments. Yes, there is more than one way to do it: in XML, with reflection, by hand, etc. I prefer doing it by hand simply because it a simple thing and doesn't require to facy of a solution - I prefer the readability and clearity of doing it plainly, but I will make sure to update the article with the other options as well.

Thanks you for the interesting feedback. 

Eugen. 

Eugen Paraschiv replied on Sat, 2012/01/07 - 8:54am in response to: Caesar Ralf Franz Hoppen

Yes, you can also obtain the class that way. My own preference is towards the simpler solution, as I find it more readable and easy to follow. 

Also, this exact issue has already been discussed in the comments of the original article. 

Regards, 

Eugen. 

Gökhan Ozar replied on Mon, 2012/02/20 - 4:58am

Did you accidentally delete part II or is it just a renaming mistake that part 3 comes after part 1 with no part 2?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.