The DAO with Spring and Hibernate


1.概述

本文将展示如何使用Spring和Hibernate实现DAO。对于核心Hibernate配置,请参阅有关Hibernate 3和Hibernate 4 with Spring的文章。

  1. No More Spring Templates

从Spring 3.0和Hibernate 3.0.1开始,不再需要Spring HibernateTemplate来管理Hibernate Session。现在可以使用上下文会话 - 由Hibernate直接管理并在整个事务范围内活动的会话。

因此,现在最好的做法是直接使用Hibernate API而不是HibernateTemplate,它将有效地将DAO层实现与Spring完全分离。

2.1。Exception Translation without the HibernateTemplate – alive and well

异常翻译是HibernateTemplate的职责之一- 将低级Hibernate异常转换为更高级别的通用Spring异常。

如果没有该模板,对于使用@Repository注释注释的所有DAO ,此机制仍然处于启用状态并处于活动状态。在引擎盖下,它使用一个Spring bean后处理器,它将使用在Spring上下文中找到的所有PersistenceExceptionTranslator来建议所有的@Repository bean 。

要记住的一件事是异常翻译是通过代理完成的; 为了使Spring能够围绕DAO类创建代理,这些代理不能被声明为final。

2.2。Hibernate Session management without the Template

当Hibernate支持上下文会话时,HibernateTemplate基本上已经过时了; 事实上,该类的javadoc已经更新了这个建议(粗体来自原文):

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

我们将从基础DAO开始 - 一个抽象的,参数化的DAO,它支持常见的泛型操作,并且意在为每个实体进行扩展:

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

   @Autowired
   private SessionFactory sessionFactory;

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

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

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

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

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

   protected final Session getCurrentSession(){
      return sessionFactory.getCurrentSession();
   }
}

这里有一些方面很有意思 - 正如所讨论的,抽象DAO并没有扩展任何Spring模板(例如HibernateTemplate)。相反,Hibernate SessionFactory直接注入DAO,并将通过它公开的上下文Session发挥主要Hibernate API的作用:

this.sessionFactory。getCurrentSession();

另请注意,实体的Class在构造函数中传递以在泛型操作中使用。

现在,让我们看一下这个DAO的示例实现,对于Foo实体:

@Repository
public class FooDAO extends AbstractHibernateDAO< Foo > implements IFooDAO{

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