使用 Spring 和 JPA 设置 DAO 层
1.概述
本文将展示如何使用 Spring 和 JPA 实现 DAO。有关核心 JPA 配置,请参阅有关 的文章。
2. 不再有 Spring 模板
从 Spring 3.1 开始,已弃用 JpaTemplate和相应的JpaDaoSupport 以支持使用本机 Java Persistence API。
此外,这两个类仅与 JPA 1 相关(来自JpaTemplate javadoc):
请注意,此类没有升级到 JPA 2.0,也永远不会升级。
因此,现在最好的做法是直接使用 Java Persistence API而不是JpaTemplate。
2.1. 没有模板的异常转换
JpaTemplate的职责之一是异常转换——将低级异常转换为更高级别的通用 Spring 异常。
如果没有模板,异常转换仍然可以为所有使用 @Repository 注解的 DAO启用并完全正常运行。Spring 使用 bean 后处理器实现这一点,该后处理器将使用容器中找到的所有PersistenceExceptionTranslator通知所有*@Repository* bean 。
同样重要的是要注意异常转换机制使用代理——为了让 Spring 能够围绕 DAO 类创建代理,这些代理不能被声明为final。
3. The DAO
首先,我们将为所有 DAO 实现基础层——一个使用泛型并设计为可扩展的抽象类:
public abstract class AbstractJpaDAO< T extends Serializable > {
private Class< T > clazz;
@PersistenceContext
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() )
.getResultList();
}
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 );
}
}
这里主要有趣的方面是EntityManager的注入方式——使用标准的*@PersistenceContext注解。在后台,这是由PersistenceAnnotationBeanPostProcessor处理的——它处理注解,从包含中检索 JPA 实体管理器并注入它。 持久化后处理器要么通过在配置中定义显式创建,要么通过在命名空间配置中定义context:annotation-config或context:component-scan*自动创建。
另外,请注意实体Class在构造函数中传递以用于通用操作:
@Repository
public class FooDAO extends AbstractJPADAO< Foo > implements IFooDAO{
public FooDAO(){
setClazz(Foo.class );
}
}