<< Eclipse Debug调试失败 hot code replace fail 几种情况 | 首页 | isnowfy/snownlp · 基于pathon 中文自然语言处理库 >>

JDBCTemplate和HibernateTemplate事物源码解析 - - ITeye技术网站

由于项目中对批量的sql进行入库处理。所以打算用jdbcTemplate。在其他的增删改查中都是用hibernateTemplate

 

在这里考虑到一个问题,就是当jdbcTemplatehibernateTemplate结合用的时候,事务是怎么样的了?

 

经过测试:在一个方法中同时使用jdbcTemplate,和hibernateTemplate对数据进行增加操作。然后抛出异常。

 

发现事务是可以正常回滚的。但为什么可以这样了?看了下源码终于了解了一些。

 

<bean id="oaTM" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory"><ref bean="oaSessionFactory"/></property>
</bean>

 

总而言之。不管是使用jdbcTemplate或者是hibernateTemplate都是对jdbc的封装,说白了,对数据库的操作还是

 

使用connection,在回滚事务的时候还是调用了connection. Rollback方法来进行回滚的。

 

这一回想,在hibernate中有个sessionFactory. getCurrentSession()方法。调用的当前的线程session

 

意思就是用当前的connection来操作数据。

 

spring管理中有这么一个类来进行当前线程的数据绑定:TransactionSynchronizationManager

 

public abstract class TransactionSynchronizationManager

 

/* */ {

 

/* 77 */ private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);

 

/* */

 

/* 80 */ private static final ThreadLocal<Map<Object, Object>> resources = newNamedThreadLocal("Transactional resources");

 

/* */

 

/* 83 */ private static final ThreadLocal<List<TransactionSynchronization>> synchronizations = newNamedThreadLocal("Transaction synchronizations");

 

/* */

 

/* 86 */ private static final ThreadLocal<String> currentTransactionName = newNamedThreadLocal("Current transaction name");

 

/* */

 

/* 89 */ private static final ThreadLocal<Boolean> currentTransactionReadOnly = newNamedThreadLocal("Current transaction read-only status");

 

/* */

 

/* 92 */ private static final ThreadLocal<Integer> currentTransactionIsolationLevel = newNamedThreadLocal("Current transaction isolation level");

 

/* */

 

/* 95 */ private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal("Actual transaction active");

 

 

 

OpenEntityManagerInViewFilterOpenSessionInViewInterceptor等需要获取当前线程对象的类中都用到了此类。

 

在使用hibernateTemplate可以使用hibernateTemplate.sessionFactory.getCurrentSession().connection获取当前的connection对象

 

在使用jdbcTemplate获取当前的connection对象的方法是:

 

public abstract class DataSourceUtils {

 

 

public static Connection doGetConnection(DataSource dataSource) throws SQLException {

 

Assert.notNull(dataSource, "No DataSource specified");

 

 

 

//①首先尝试从事务同步管理器中获取数据连接

 

ConnectionHolder conHolder =

 

(ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);

 

if (conHolder != null && (conHolder.hasConnection() ||

 

conHolder.isSynchronizedWithTransaction())) {

 

conHolder.requested();

 

if (!conHolder.hasConnection()) {

 

logger.debug("Fetching resumed JDBC Connection from DataSource");

 

conHolder.setConnection(dataSource.getConnection());

 

}

 

return conHolder.getConnection();

 

}

 

 

 

//②如果获取不到连接,则直接从数据源中获取连接

 

Connection con = dataSource.getConnection();

 

 

 

//③如果拥有事务上下文,则将连接绑定到事务上下文中

 

if (TransactionSynchronizationManager.isSynchronizationActive()) {

 

ConnectionHolder holderToUse = conHolder;

 

if (holderToUse == null) {

 

holderToUse = new ConnectionHolder(con);

 

}

 

else {holderToUse.setConnection(con);}

 

holderToUse.requested();

 

TransactionSynchronizationManager.registerSynchronization(

 

new ConnectionSynchronization(holderToUse, dataSource));

 

holderToUse.setSynchronizedWithTransaction(true);

 

if (holderToUse != conHolder) {

 

TransactionSynchronizationManager.bindResource(

 

dataSource, holderToUse);

 

}

 

}

 

return con;

 

}

 

 

}

 

当在同在方法中打印出这两个种方法获取的connection对象是同一对象时,基本上证明了在使用jdbcTemplatehibernateTemplate的时候。

阅读全文……




发表评论 发送引用通报