public class ProductDaoImpl implements ProductDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
public Collection loadProductsByCategory(String category) {
return this.sessionFactory.getCurrentSession()
.createQuery("from test.Product product where product.category=?")
.setParameter(0, category)
.list();
这种Hibernate数据访问的风格与你在Hibernate文档和示例中见到的非常类似,除了DAO实现类中持有了一个 SessionFactory
的实例变量。
我们强烈推荐这种基于实例变量的DAO构建方式,而不是使用那种过去由Hibernate的示例程序中提到的 静态的
HibernateUtil
类。
(通常来说,不要在静态变量中保存任何资源信息除非 确实 有这个必要)。
上面我们所列出的DAO完全遵循IoC:它如同使用Spring的 HibernateTemplate
进行编程那样,适合在application context中进行配置。
具体来说,它使用了Setter注入;如果你愿意,完全可以使用Constructor注入方式替代。当然,这样的DAO还可以建立在一个普通的Java类中(诸如在Unit Test中): 仅仅需要初始化这个类,
调用 setSessionFactory(..)
方法设置你所期望的工厂资源。 以Spring的bean的定义方式,它看上去就像这样:
<beans>
<bean id="myProductDao" class="product.ProductDaoImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
</beans>
这种DAO访问方式的主要优势在于它仅仅依赖于Hibernate API本身而无需引入任何Spring的类。
从无入侵性的角度来看,这一点非常吸引人。同时,对于Hibernate开发人员来说也更自然。
然而,这样的DAO访问方式会抛出 HibernateException
,这是一个无需声明或捕获的unchecked exception。
这意味着,DAO的调用者只能以普通的错误来处理这些异常,除非完全依赖Hibernate自身的异常体系。
因而,除非你将DAO的调用者绑定到具体的实现策略上去,否则你将无法捕获特定的异常原因(诸如乐观锁异常)。
这种折中平衡或许可以被接受,如果你的应用完全基于Hibernate或者无需进行特殊的异常处理。
幸运的是,Spring的 LocalSessionFactoryBean
可以在任何Spring的事务管理策略下,
提供对Hibernate的 SessionFactory.getCurrentSession()
函数的支持,它将返回当前受Spring事务管理(甚至是 HibernateTransactionManager
管理的)的 Session
对象。
当然,该函数的标准行为依然有效:返回当前与正在进行的JTA事务(无论是Spring的 JtaTransactionManager
、EJB CMT或者普通的JTA)绑定的 Session
对象。
总体来说,DAO可以基于Hibernate3的原生API实现,同时,它依旧需要能够参与到Spring的事务管理中。
这对于那些已经对Hibernate非常熟悉的人来说很有吸引力,因为这种方式更加自然。
不过,此时的DAO将抛出HibernateException,因而,如果有必要的话,需要明确地去做由 HibernateException
到Spring的 DataAccessException
的转化。