spring事务-实现原理

1,285 阅读3分钟

最终的事务提交

主要有2个实现
1.hibernate
2.数据源

即调用的是orm框架的事务,orm框架的事务调用的又是jdbc客户端即jdbc api 连接connection的提交方法。


hibernate

public class HibernateTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, BeanFactoryAware, InitializingBean {
protected void doCommit(DefaultTransactionStatus status) {
//获取hibernate事务管理器
  HibernateTransactionManager.HibernateTransactionObject txObject = (HibernateTransactionManager.HibernateTransactionObject)status.getTransaction();
  if (status.isDebug()) {
    this.logger.debug("Committing Hibernate transaction on Session [" + SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
  }

  try {
//提交事务
    txObject.getSessionHolder().getTransaction().commit(); //提交事务
  } catch (TransactionException var4) {
    throw new TransactionSystemException("Could not commit Hibernate transaction", var4);
  } catch (HibernateException var5) {
    throw this.convertHibernateAccessException(var5);
  }
}

数据源

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
protected void doCommit(DefaultTransactionStatus status) {
 //获取数据源事务管理器
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)status.getTransaction();
  Connection con = txObject.getConnectionHolder().getConnection();
  if (status.isDebug()) {
    this.logger.debug("Committing JDBC transaction on Connection [" + con + "]");
  }

  try {
//提交事务
    con.commit(); //提交事务
  } catch (SQLException var5) {
    throw new TransactionSystemException("Could not commit JDBC transaction", var5);
  }
}

线程

一个请求下来,这个请求线程可能包含了很多个事务,那怎么传播事务?
1.每个事务,都创建新的事务
2.只创建第一个事务,后面的事务共用第一个事务,就不创建新的事务了


各自的优缺点?应用场景?
略。


公司系统目前是哪种情况?传播规则是怎样的?

配置

<!-- transaction -->
<bean id="transactionManager_trade"
 class="org.springframework.orm.hibernate3.HibernateTransactionManager"> //hibernate事务管理器
 <property name="sessionFactory">
  <ref bean="sessionFactory_trade" />
 </property>
</bean>

<!-- 声明式事务-->
<tx:advice id="txAdvice_trade" transaction-manager="transactionManager_trade">
 <tx:attributes>
  <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
  <tx:method name="insert*" rollback-for="hikefa.core.exception.BizException" />
  <tx:method name="update*" rollback-for="hikefa.core.exception.BizException" />
  <tx:method name="delete*" rollback-for="hikefa.core.exception.BizException" />
  <tx:method name="*" rollback-for="hikefa.core.exception.BizException" /> //所有方法都加事务
 </tx:attributes>
</tx:advice>

<aop:config proxy-target-class="true">
 <aop:advisor advice-ref="txAdvice_trade" pointcut="execution(* xxx.trade.dbservice.impl..*Service*.*(..))" /> //所有service类的所有业务方法都加事务
</aop:config>

默认传播规则是?
如果当前线程已经有事务,就不创建新的事务。如果没有,才创建新的事务。

举例说明,总结
1.代码

非service类的方法(){
1.调用service1.方法; //比如,创建支付订单
2.调用service2.方法。//比如,创建支付订单明细
}

2.那么现在的事务传播规则是?
1)调用service1.方法 //方法结束之后,就已经提交事务了
2)调用service2.方法 //由于上面的事务已经提交和结束了,所以这次又会创建新的事务对象,然后在方法结束的时候,这个新的事务对象会去提交事务

3.spring默认的事务传播规则是?
代码

service0类的业务方法(){ //创建新的事务
1.调用service1类.业务方法; //当前线程已经有了事务,就不再创建新的事务对象 //方法结束的时候,那还提交吗?
2.调用service2类.业务方法。//当前线程已经有了事务,就不再创建新的事务对象 //方法结束的时候,那还提交吗?
}

这个时候,相当于有3个事务,但是是共用一个(即共用第一个事务对象),但是提交事务是每次每个方法结束的时候提交,还是最后一起提交(即由service0类的业务方法结束的时候提交),只提交一次?
只提交一次,因为事务是原子操作,不管这个事务包含了几个子事务(即嵌套事务),所以如果有嵌套事务,就以最外层的事务为准,它提交才是真的提交,而且最外层的事务只提交一次,就是在最外层的业务方法结束的时候。


表示事务对象的核心类和线程的关系

每个请求线程的事务是如何和当前线程绑定的?基于ThreadLocal。

参考

深入解析spring架构和实现原理