如果一个方法中既用了HibernateTemplate,又用了JdbcTemplate,应该怎么配单实例的db事务呢(多例免谈)用DataSouceTransactionManager是不行的,而用HibernateTransactionManager就可以保证
原因的话看下它们源代码,会发现HibernateTransactionManager中的处理可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接
原文如下=====================================================================
今天这边报出一个问题,他在一个service方法里面,用了jdbcdaosupport的dao又用了hibernateDaoSupport的dao,在spring里面给service方法配上了事务,
但是通过mysql的bin log,发现这种不同的dao使用的连接id不是同一个,即jdbctemplate使用了一个链接,而hibernatetemplate使用了另外一个链接,这样虽然两种dao都是针对一个mysql实例,但却没法保证事务。
之前xd提过使用hibernateTransaction manager,可以保证混用时候的事务,但是却不知道为啥会这样。我们这边就以为datasourcetransactionmanager也是一样,但发现事实上不一样。确实我们换成hibernateTransaction manager,两种dao使用的connection就归一了,真好,但是为啥呢?
翻了半天spring的源代码终于找到了。
以下是datasourceTransactionManager的doGetTransaction和doBegin代码
protected Object doGetTransaction() {
//只是设定一个dataSource为key的存放connection的threadlcal
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
protected void doBegin(Object transaction, TransactionDefinition definition) {
.....
try {
if (txObject.getConnectionHolder() == null ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
}
....从datasource拿一个连接,放入thread生命周期的holder
}
这就完了。
然后jdbctemplate会通过datasourceutil去拿这个holder里面的connection
从而在一个事务里使用这个连接。
但是hibernateTransactionManager呢:
protected Object doGetTransaction() {
HibernateTransactionObject txObject = new HibernateTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if (sessionHolder != null) {
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound Session [" +
SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
}
txObject.setSessionHolder(sessionHolder, false);
}
if (getDataSource() != null) {
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.getResource(getDataSource());
txObject.setConnectionHolder(conHolder);
}
return txObject;
}
两个holder都管!
protected void doBegin(Object transaction, TransactionDefinition definition) {
.....
try {
if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
Interceptor entityInterceptor = getEntityInterceptor();
Session newSession = (entityInterceptor != null ?
getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
if (logger.isDebugEnabled()) {
logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
"] for Hibernate transaction");
}
txObject.setSessionHolder(new SessionHolder(newSession), true);
}
.....从sessionFactory拿个新session,也会产生一个新连接
session = txObject.getSessionHolder().getSession();
if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
// We're allowed to change the transaction settings of the JDBC Connection.
if (logger.isDebugEnabled()) {
logger.debug(
"Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
}
//原来直接把session后面的connection也放入holder
Connection con = session.connection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
}
分享到:
相关推荐
2、配置数据源,注入JdbcTemplate,启用事务管理,注入DataSourceTransactionManager 3、传播机制 @see Propagation#REQUIRED 支持当前事务,如果没有则新建一个事务, 例:a方法调用b方法,如果a方法有事务,则b加入...
BeanDefinition则详细描述了bean的配置信息,如类名、作用域、依赖等,为Bean的创建和管理提供了蓝图。 除此之外,文档还深入介绍了Spring的事务管理能力,特别是DataSourceTransactionManager,它为数据库操作提供...
9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...
9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 ...
9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...
9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...
9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...
概念:面向切面编程,在不改变源码的情况下对方法进行增强,抽取横切关注点(日志处理,事务管理,安全检查,性能测试等等),使用AOP进行增强,使程序员只需要关注与业务逻辑编写. 专业术语 目标Target:需要增强的类 ...
<bean id="transactionManagerPdm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager " p:dataSource-ref="dataSourcePdm"/> <!-- 配置事务的传播特性 --> *" propagation=...
在Spring3中配置数据源,包括DBCP,C3P0,Proxool,Bonecp主要的数据源,里面包含这些数据源的jar文件和依赖文件及配置文件。。 如Bonecp目前听说是最快的数据源,速度是传统的c3p0的25倍, bonecp.properties文件: ...
springboot-jdbc-aop-transactional-demo
3. 在session 中完成对数据的增删改查和事务提交等. 4. 在用完之后关闭session 。 5. 在java 对象和 数据库之间有做mapping 的配置文件,也通常是xml 文件。 mybatis实战教程(mybatis in action)之一:开发环境搭建 ...
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> <property name="dataSource" ref="dataSource"></property> ...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- Spring AOP config配置切点 --> (* com.org.service.*.*(..))" id=...
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--配置事务的通知--> *" propagation="REQUIRED"/> *" propagation="REQUIRED"/> *" ...
-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 配置事务通知属性 --> ...
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> <bean id="processEngineConfiguration" class="org.activiti.spring...