先看一段代码:
Connectionconn = Conn.getConnection();
conn.setAutoCommit(false);
……..
……...
conn.rollback();
conn.commit();
数据库的事务是针对 Connection 的。
接着再看一段代码:( spring 中事务的一段学习代码,这段代码是把spring 和 hibernate结合在一起的,增加了理解上的难度,因为我的出发点一开始不要hibernate ,就光用 jdbc来进行数据库事务,但是没有其他好的代码,就这样吧)
public Long addLineItem(Long orderId, LineItemlineItem){
log("OrderListDAOHibernate.addLineItem : Start...");
OrderList orderList = (OrderList)getHibernateTemplate().load(OrderList.class, orderId);
lineItem.setOrderList(orderList);
getHibernateTemplate().saveOrUpdate(lineItem);
getHibernateTemplate().saveOrUpdate(orderList);
log("OrderListDAOHibernate.addLineItem : Ending...");
return lineItem.getId();
}
在这个代码的配置文件中,把 addLineItem做为一个切入点,进行事务,也就是说,在 addLineItem的外面,再包上一层事务的外壳。
但是这个时候,问题出来了,事务是针对 Connection的,而上面的两个连续的 HibernateTemplate 执行的 saveOrUpdate 中的Connection 必须是一致才能用事务, spring怎么做到这一点的呢?(这个问题也就是在找 spring的事务例子前,我想的 spring 中用 jdbc 来进行事务,怎么样让Connection 保持一致呢?但是没有 jdbc 的例子,只有整合 hibernate或者 ibatis 的例子,但是,我想,原理是一样的吧。)
解决问题的思路: HibernateTemplate 中的 Connection必定一致。那么就从 HibernateTemplate 入手。
看spring 的源代码,既然是 Hibernate ,那么,就没有 Connection给你看,只有 Session ,由 Session 来管理 Connection,那么用事务来控制的话,这个 Session必定在所有该事务中是一致的。于是在 HibernateTemplate中找到:
protected Session getSession() {
if (isAlwaysUseNewSession()) {
return SessionFactoryUtils.getNewSession(getSessionFactory(),getEntityInterceptor());
}
else if (!isAllowCreate()) {
return SessionFactoryUtils.getSession(getSessionFactory(),false);
}
else {
return SessionFactoryUtils.getSession(
getSessionFactory(), getEntityInterceptor(),getJdbcExceptionTranslator());
}
}
看来在 SessionFactoryUtils 里面,接着在SessionFactoryUtils.getSession 中找:
这个方法太长了,太复杂了,从简,发现了非常关键的一点:
SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
假如 sessionHolder不等于空,说明,在事务中有这样一个还没有 commit 的 session,那么就返回这个 session ,假如等于空,新建一个 session,并且在事务里加入这个 session。这段代码的意思大概是这样,太繁杂了,只能猜,也肯定是如此。
再看 getHibernateTemplate() 方法来自继承 HibernateDaoSupport,看了电子书《 spring-reference 》的第九章“ Dao 支持”, Dao的支持类可以有好多,如: JdbcDaoSupport , HibernateDaoSupport ,JdoDaoSupport 等等。
既然前面一开始就是从 jdbc 的 spring事务控制引起的,那么看到了同样的HibernateDaoSupport---JdbcDaoSupport ,那么 JdbcDaoSupport 也应该有getJdbcTemplate() 这个方法,并且返回 JdbcTemplate 这个类。
果然如此。
于是剖析 JdbcTemplate 是不是和 HibernateTemplate一样。果然一样。
注意到:
Connection con =DataSourceUtils.getConnection(getDataSource());
Connection 是从 DataSourceUtils.getConnection() 来的,继续跟踪DataSourceUtils.getConnection() 。
找到:
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
和 Hibernate 中的一模一样,因为没有了 session 的封装,条理在jdbc 中更加清晰了。