Spring整合Hibernate之Session

转载:http://bbs.tech.ccidnet.com/read.php?tid=557959

Spring整合Hibernate时,主要做了两件事:提供事务级session和声明式的事务控制。
在较早的Hibernate中,对于session的管理一般是one-session-per-operation的方式,即一次具体操作一个session。
Spring为了解决这个问题,引入了HibernateTemplate类。
先来看看它的文档中一段很有意思的话:
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 SessionFactory.getCurrentSession().(Spring’s LocalSessionFactoryBean automatically supports Spring transaction management for the Hibernate3 getCurrentSession() method.)作者说:在新开始的工程,可以考虑用标准的Hibernate3的编码方式作为HibernateTemplate的替代。因为Hibernate3提供的SessionFactory.getCurrentSession()已经取代了以往那种每次操作都open一个新Session的方式,同时Spring的LocalSessionFactoryBean自动支持Hibernate3的getCurrentSession()的事务管理。也就是说,如果不用HibernateTemplate这咱Spring的专有API,而只用Hibernate3,我们一样可以受用Spring的事务管理。
来详细地看看HibernateTemplate,因为它毕竟简化了Hibernate的操作,但是在有些情况下,我们应该使用Hibernate而不是用HibernateTemplate。根据HibernateTemplate的文档注释,它做了两件事:1.简化了Hibernate的数据访问编码;2.自动地将HibernateExceptions转化为Spring的异常体系中的DataAccessExceptions(这是一个unchecked exception).
HibernateTemplate实现第一点,是通过回调来实现的,它的核心方法execute(): public Object execute(HibernateCallback action, boolean exposeNativeSession) m_),}
throws DataAccessException {
//这个Session是受Spring事务管理的
Session session = getSession();
//这个是怎么回事,还要再仔细看看,我想它应该是关系到Session在这个操作里操作完是否关闭的关键
boolean existingTransaction = SessionFactoryUtils
.isSessionTransactional(session, getSessionFactory()); FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
//在默认情况下,不把Sessin暴露给用户
Session sessionToExpose = (exposeNativeSession ? session :
createSessionProxy (session));
//exposeNativeSession默认值为false ;
//这里是真正涉及到Hibernate操作的地方
Object result = action.doInHibernate(sessionToExpose);
flushIfNecessary(session, existingTransaction);
return result; }
}
catch(…){
//将Hibernate代码抛出的HibernateException,SQLException
//转化为 DataAccessExceptions,如果有运 行时异常,将其抛出
}
}
finally {
if (existingTransaction) {
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
//这里的默认值是false,所以此次操作结束后,session不会在此关闭
SessionFactoryUtils.closeSession(session);
}
else {
//没有硬性关闭Session,这是区别于Hibernate3以前版本的地方 SessionFactoryUtils.closeSessionOrRegisterDeferredClose
(session, getSessionFactory());
}
}
}
}
真正的数据操作是在HibernateCallback action中实现的,为了执行action中的操作,需要一个Session,这个Session是在execute()方法内部获得(不一定是新产生的)并传入的。另外,在操作执行完之后,这个Session没有硬性关闭,而是交由SessionFactoryUtils来决定是否立即关闭还是延迟关闭。有时间再看看SessionFactoryUtils .closeSessionOrRegisterDeferredClose()具体做了些什么。
用HibernateTemplate比起直接用Hibernate编码简洁了很多。但是,作者在文档中写到:The major advantage is its
automatic conversion to DataAccessExceptions, the major disadvantage that no checked application exceptions can get
thrown from within data access code.因为封闭得太好了,我们根本无法干预HibernateTemplate的方法内部,因此我们
不能抛出检查型的应用异常。如果我们想在某个方法的内部在某个条件下抛出自定义的应用异常,就要用Hibernate直接编码了,这是不应该用HibernateTemplate的情况。
作者在文档中还写到:It can be used within a service implementation via direct instantiation(实例)with a SessionFactory reference, or get prepared in an application context and given to services as bean reference. 为了使用
HibernateTemplate,我们需要一个SessionFactory,因为使用HibernateTemplate时需要获取Session,而Session是从SessionFactory获取的。我们可以在应用配置文件中,根据已配置的SessionFactory配置一个HibernateTemplate,或者在程序中要用时再根据已配置好的SessionFactory来产生一个HibernateTemplate。Spring提供了一个可配置的SessionFactory的工厂类,用以向容器暴露一个单例化的SessionFactory:LocalSessionFactoryBean。这个类的源码也很有意思,还要继续看一下。
为了进一步简化Hibernate的操作,Spring提供了一个用于DAO的基类HibernateDaoSupport:This base class is mainly
intended for HibernateTemplate usage。这个类只有唯一的成员变量private HibernateTemplate hibernateTemplate。但是我在想,Spring是不是做的太过分了?包装得太好了??

对于使用sessionFactory.getCurrentSession()方式下,会自动更改autocommit=false,建议以事务方式运行。而openSession(),autocommit则不会改动。
在Spring中SessionFactoryUtils.doGetSession()实现Session的获取。

发表评论

邮箱地址不会被公开。 必填项已用*标注

昵称 *