Simplify the DAO with Spring and Java Generics

Table of Contents

1. Overview

This article will focus on simplifying the DAO layer by using a single, generified Data Access Object for all entities in the system, which will result in elegant data access, with no unnecessary clutter or verbosity.

2. The Hibernate and JPA DAOs

Most production codebases have some kind of DAO layer. Usually the implementation ranges from multiple classes with no abstract base class to some kind of generified class. However, one thing is consistent – there is always more then one – most likely, there is a one to one relation between the DAOs and the 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 a base abstract class.

These multiple implementations can usually be replaced by a single parametrized DAO used in such no functionality is lost by taking full advantage of the type safety provided by Java 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.1. The Abstract Hibernate DAO

public abstract class AbstractHibernateDao< T extends Serializable > {

   private Class< T > clazz;

   @Autowired
   SessionFactory sessionFactory;

   public final void setClazz( Class< T > clazzToSet ){
      this.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 create( T entity ){
      getCurrentSession().persist( entity );
   }

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

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

   protected final Session getCurrentSession(){
      return 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 Hibernate DAO tutorial.

2.2. The Generic Hibernate DAO

Now that the abstract DAO is done, we can implement it just once – the generic DAO implementation will become the only implementation needed:

@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.

The IGenericDao is simply an interface for all the DAO methods, so that we can inject our implementation with Spring in (or in whatever is needed):

public interface IGenericDao<T extends Serializable> {

   T findOne(final long id);

   List<T> findAll();

   void create(final T entity);

   T update(final T entity);

   void delete(final T entity);

   void deleteById(final long entityId);
}

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 entityManager.find( clazz, id );
   }
   public List< T > findAll(){
      return entityManager.createQuery( "from " + clazz.getName() )
       .getResultList();
   }

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

   public void update( T entity ){
      entityManager.merge( entity );
   }

   public void delete( T entity ){
      entityManager.remove( entity );
   }
   public void deleteById( Long entityId ){
      T entity = getById( entityId );
      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 JPA DAO

Similar to the the Hibernate implementation, the JPA Data Access Object is straighforward as well:

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericJpaDao< T extends Serializable >
 extends AbstractJpaDao< T > implements IGenericDao< T >{
   //
}

3. Injecting this DAO

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 ){
      dao = daoToSet;
      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.

There are of course other ways that the class can be specified for the DAO – via reflection, or even in XML. My preference is towards this simpler solution because of the improved readability and transparency compared to using reflection.

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.

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

Get My 3 Spring eBooks
Learn how to properly build Web App with Spring (and how to prototype 90% of it very quickly)
×
Download the 3 eBooks - Build Your App "The Right Way"

, , , ,

  • Timo Westkämper

    You might want to consider using Spring Data instead. It provides a neat DAO/Repository abstraction layer for multiple backends, including JPA.

  • Amuraco

    Is there any way to avoid having to do setClazz(XYZ.class) during injection? It seems like it a critial piece

    • Eugen

      The Class is there to help some queries that need it – you could, potentially do without it, but you would need to find a way around those queries. Having the class available there is just easier.

    • http://www.gravatar.com/avatar/01795b4543b30b3cf29f6a204465c2e3.png Bogdan Marian

      I have used something like this in one of my projects:

      public class EntityManager implements Serializable {

      private static final long serialVersionUID = 1L;
      private Class entityType;

      @SuppressWarnings(“unchecked”)
      protected Class getEntityType() {
      if (entityType == null) {
      ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
      entityType = (Class) parameterizedType.getActualTypeArguments()[0];
      }

      return entityType;
      }
      }

      And then the class which knows the entity class:

      public class CategoryHome extends EntityManager{

      }

      When trying to query the DB using JPA/Hibernate, you now have access to the entity class…

    • baeldung

      It can be done via reflection, but it seems like overkill for the article.

  • Cmordant1

    You can also use spring data jpa that does the same Thing + more

  • http://service.ztronics.com Motherboard Repair

    It’s good about elegant data access. It provides fastest access in Java.

  • http://dmenounos.myopenid.com/ Dimitris

    Nice introduction to the generic repository pattern. However the proposed prototype scope is a bad idea IMHO. Instead define concrete subclasses that encapsulate the necessary configuration. e.g.:

    @Repository
    public class CustomerDAO extends AbstractJpaDAO {

    public CustomerDAO() {
    setClazz(Customer.class );
    }
    }

    This is more semantically correct code. It also safer; a “client” cannot forget to initialize it properly. Moreover it provides a dedicated space for “customer” specific operations, works wonders for IDEs (searching, refactoring, etc.) and keeps your server memory consumption at minimum by using only a single instance.

    • Eugen

      Well, this is the standard approach and it has advantages and disadvantages – for one, and this is important, you would have a lot of code duplication – lots of classes essentially doing nothing special – this has costs and is overly verbose, one of the major problems in Java. Also, for a large codebase, you could potentially end up with hundreds of these classes (multiplied by two assuming you’re using an interface for each one as well). The prototype scope may mean a few more objects, but really, these are extremely lightweight (stateless) so it’s very unlikely that this would be a problem. So, as I said, a compromise; I am personally leaning towards a concise implementation that is easy to change rather than worry about a few more objects in the heap.
      Thanks for the interesting feedback.
      Eugen.

      • LG Optimusv

        “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.”: I would like to see a complex case where a prototype-scoped DAO is better than a singleton-scoped DAO. I think the only case a prototype-scoped DAO is needed is that that DAO stores some states (i.e. it has member variables), but then why does a DAO need to store states?

        • baeldung

          I was thinking of the instance of a Class which is helpful when writing some queries. That would be the only state that requires the prototype scope; if that’s not the case (and if using things like spring-data it’s not in all likelihood necessary) then the prototype scope is not necessary and we can just inject the simple generic dao with different generic parameters and let erasures do the rest.
          Thanks for pointing it out – I’ll update the article accordingly.
          Eugen.

    • Victor

      I totally agree with Dimitris on this one. Having the concrete subclass really helps with the readability and clarity of the code. IMO, a better clarity is to e chosen, even if you might end up with some concrete subclasses that have few specific operations.

      • Eugen

        I do agree that in some cases, having a concrete class for each entity would make sense. Let’s look however at the advantages mentioned:
        - dedicated customer operations – the operations are not dedicated, and that’s the whole point; in fact the operations are standard, there’s nothing special about getting all of Foo or getting all of Bar; Spring data does the same – it provides the common operations in a common interface you extend, just because the is nothing specific about the operations
        - IDE support – in fact, no, that isn’t the case either; refactoring or opening up the implementation of an operation will still lead to the abstract dao and not the concrete one (which is empty) so the entire interaction through the IDE will pretty much ignore the concrete class
        - support for specific operations – yes, that’s a good reason to have a concrete class; the pattern works perfectly fine with a few concrede implementations that actually do have a reason to exist and the rest of the data access done thought the generic class; creating concrete implementations just in case seems to me as a premature (and costing) optimization
        - the memory consumption – I addressed this one before in a comment on this article – again, memory is cheap – don’t optimize until there is a need to do so; if the profiler actually shows you that ~20 light DAO objects really make a difference, by all means; keep in mind that just a single Spring request will generate hundreds of light objects though and don’t optimize memory early – it’s almost always not a good idea
        - clarity – again, the concrete class is empty, so there almost no interaction with it whatsoever, so I don’t see it adding to much clarity to the mix; however having potentially over a hundred concrete and empty classes will surely decrease the clarity and the conceptual load of the system
        I will again mention that this is the direction that Spring Data has taken as well (taken one step further of course).
        Hope this keeps the discussion going.

    • baeldung

      Well what you’re describing is the standard way to implement the pattern. What I am aiming to describe here is an alternative way. Yes, you need to remember to initialize it, which is a downside. However, in a large enough system, with a high number of copy-paste DAO implementation, the upside of getting rid of all that cruft may be well worth it.
      Thanks.

      • Girish Mahajan

        you’d try using:

        clazz = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

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

          Hey Girish – yes, this has been proposed a few years back – also in the comments of this article. While it’s a valid approach, I prefer to pass the class, since it’s a bit more readable. Hope this makes sense. Cheers,

          Eugen.

  • http://twitter.com/horte Fredrik Hörte

    In the code example for “The Service” you say: class FooService implements IFooService

    Though, since you are using IGenericDAO shouldn’t it implement IGenericDAO?

  • Meeraj

    How is this different from using the entity manager directly from your servivce class. IMHO the whole idea of using DAOs is an unncessary level of indirection.

    Meeraj

    • baeldung

      One difference is the flexibility to change – using the entity manager directly means tying much of the codebase to the JPA API. Using a DAO means tying a single class, so if you ever want to change – you only change this single class, with a clear responsibility. However, I fully agree – not all projects need a DAO and many projects use one without a good reason to – this is for when a DAO layer is actually needed.

  • Anonymous

    I’ve downloaded the project from github.com/eugenp/REST, set up a HSQL database (don’t have mySql on this computer) and try to start the server or run the tests but get this exception

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘barService’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.rest.persistence.dao.bar.IBarDAO org.rest.persistence.service.bar.impl.BarService.dao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.rest.persistence.dao.bar.IBarDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    The github project is slightly different from the source above, namely the service has a IFooBar instead of an IGenericDAO but nevertheless, nowhere can I find the declaration/definition of an IFooBar implementation thus the above exception.

    What’s missing?

    • baeldung

      The github project has been evolved since this article was written. If you are having this problem with the current project, please go ahead and open a issue on github and I will take a look.
      Thanks.
      Eugen.

  • Friend

    Nice, thanks for the post, just one thing, injecting a “fat” generic DAO into every use case, even ones that don’t require all of the functionality probably ain’t the best.

    A possible refinement of this would be to divide the generic interface into smaller ones each of which defining a function, eg IPersistable, IDeleteable, IUpdateable, IRetrievable. Might have to forgo not creating sub interfaces for particular use cases, but i prefer a leaner use case than a leaner code base

    Then ensure that you inject by only the interface thats required, hiding some of the additional functionality that is perhaps not required by a particular use case.

    Otherwise we end up with having to override certain methods and throw some nasty exceptions to illustrate the fact that this particular use case is not supposed to save entities for example. 2 cents

    • baeldung

      In my view, that depends on what your application looks like. I described a very standard DAO-Service-Controller (presumably) separation of responsibilities – if that’s the case, you can always choose to publish a smaller or more focused API from the Service layer if that makes sense. Splitting this DAO into a few responsibilities may also make sense, but these smaller and more focused responsibilities (and APIs) can still use the same technique – have a single, generic implementation instead of many similar ones.
      Thanks for the feedback.
      Eugen.

  • http://twitter.com/sangdolha Sanghyun Lee

    In you AbstractHibernateDAO class, there’s no getById method. Maybe, typo of findOne?

    • baeldung

      findOne is getById yes.

  • Les

    I think I missed something. Where does “IGenericDAO” come from? I don’t see any definition of it. Don’t you just mean “GenericDAO”?

    • Les

      I think I see a little more. Is IGenericDAO suppose to be an interface of the methods in Abstract[Hibernate|Jpa]DAO? If so, shouldn’t those classes implement IGenericDAO?

      • baeldung

        Yes, IGenericDao is simply the interface used to inject the implementation – I edited that area of the article to make it more clear.
        Thanks.

  • Vikram

    I agree with the approach of having a lean code and not having numerous empty DAOs. However, why can’t we have the class “AbstractJpaDao” as a concrete class and make it a @Repsoitory. Any downsides? Please explain.

    • baeldung

      It’s definitly possible – in fact, the difference between these 2 approaches is very small. The only reason I still have the abstract class is to allow the old approach to still work (individual concrete classes, extending the abstract DAO). This is very useful for migrating, because it’s not an all or nothing decision. Also, it is very likely that you may still need concrete individual implementations for specific methods – in which case, the Abstract base DAO again makes sense.
      Thanks for the feedback.
      Eugen.

  • LukasEder

    We also have a single generic DAO in jOOQ, something that our customers value high as it keeps them from writing the same repetitive CRUD on that layer time and again. If they want to add more specific methods, they can just inherit from a generated DAO…

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

      Makes perfect sense – I think that’s the way to go for the simple and standard operations.
      I’m planning to explore jOOQ soon – and I’ll probably get to use this.
      Cheers,
      Eugen.

      • http://www.jooq.org Lukas Eder

        Great, I’m looking forward to that post!

  • Rodislav Moldovan

    it would be nice to have an example for mybatis

  • Karolis B

    What about more complexed cases like some filtering/querying data by specific fields? I see this approach suitable on for very generic crud operations

  • Victor Posmagel

    super tutorial, multumesc!