The DAO with JPA and Spring – 带有JPA和Spring的DAO

最后修改: 2013年 8月 15日


1. Overview


This article will show how to implement the DAO with Spring and JPA. For the core JPA configuration, see the article about JPA with Spring.


2. No More Spring Templates


Starting with Spring 3.1, the JpaTemplate and the corresponding JpaDaoSupport have been deprecated in favor of using the native Java Persistence API.

从Spring 3.1开始,JpaTemplate和相应的JpaDaoSupport 已经被弃用,转而使用本地Java Persistence API。

Also, both of these classes are only relevant for JPA 1 (from the JpaTemplate javadoc):

另外,这两个类都只与JPA 1有关(从JpaTemplate javadoc)。

Note that this class did not get upgraded to JPA 2.0 and never will.

请注意,这个类没有被升级到JPA 2.0,而且永远不会被升级。

As a consequence, it is now best practice to use the Java Persistence API directly instead of the JpaTemplate.

因此,现在的最佳做法是直接使用Java Persistence API而不是JpaTemplate

2.1. Exception Translation Without the Template


One of the responsibilities of JpaTemplate was exception translation – translating the low-level exceptions into the higher level, generic Spring exceptions.


Without the template, exception translation is still enabled and fully functional for all DAOs annotated with @Repository. Spring implements this with a bean postprocessor which will advise all @Repository beans with all the PersistenceExceptionTranslator found in the Container.

在没有模板的情况下,对于所有用@Repository注解的DAO来说,异常翻译仍然是启用的,而且功能齐全。Spring通过一个Bean Postprocessor来实现这一点,它将用容器中发现的所有@RepositoryBean的PersistenceExceptionTranslator来通知所有@RepositoryBean。

It is also important to note that the exception translation mechanism uses proxies – for Spring to be able to create proxies around the DAO classes, these must not be declared final.


3. The DAO


First, we’ll implement the base layer for all the DAOs – an abstract class using generics and designed to be extended:


public abstract class AbstractJpaDAO< T extends Serializable > {

   private Class< T > clazz;

   EntityManager entityManager;

   public final 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() )

   public void create( T entity ){
      entityManager.persist( entity );

   public T update( T entity ){
      return entityManager.merge( entity );

   public void delete( T entity ){
      entityManager.remove( entity );
   public void deleteById( long entityId ){
      T entity = findOne( entityId );
      delete( entity );

The main interesting aspect here is the way the EntityManager is injected – using the standard @PersistenceContext annotation. Under the hood, this is handled by the PersistenceAnnotationBeanPostProcessor – which processes the annotation, retrieves the JPA entity manager from the contains and injects it.


The persistence post processor is either created explicitly by defining it in the configuration or automatically, by defining context:annotation-config or context:component-scan in the namespace config.


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


public class FooDAO extends AbstractJPADAO< Foo > implements IFooDAO{

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

4. Conclusion


This tutorial illustrated how to set up a DAO layer with Spring and JPA, using both XML and Java based configuration. We also discussed why not to use the JpaTemplate and how to replace it with the EntityManager. 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 a Maven-based project, so it should be easy to import and run as it is.