环境

  数据库: oracle 11g

  JAR:

    • org.springframework:spring-jdbc:4.3.8.RELEASE
    • org.mybatis:mybatis:3.4.2

概念

  REQUIRED(默认): 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。

  REQUIRED_NEW: 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动,如果存在当前事务,在该方法执行期间,当前事务会被挂起

  早前对NEW的理解只是停留在: 当前方法会新开启一个事务,新事务的提交/回滚不会影响之前事务的提交/回滚。

  但"当前事务会被挂起",那么NEW事务结束后,被挂起的当前事务应该是会恢复,但会恢复哪些东西了? 

  (摘自: 在Spring中使用PROPAGATION_REQUIRES_NEW带来的缓存问题?)

源码分析:

在TransactionTemplate的<T> T execute(TransactionCallback<T> action)中会通过TransactionManager的getTransaction方法来取得TransactionStatus

1、取得当前线程所关联的SessionHolder

2、若存在SessionHolder并且开启了事务(this.sessionHolder != null && this.sessionHolder.getTransaction() != null),而且当前的的传播行为为PROPAGATION_REQUIRES_NEW

3、挂起当前线程绑定的事务及其事务同步器,取消当前线程和当前session和connection的绑定,并保存所有的挂起信息以供恢复

4、创建新的session,并开启新的事务

5、执行TransactionTemplate的TransactionCallback回调

6、在新事务提交后,会恢复上个事务的所有信息和执行

测试问题描述

1、 method_A(T1事务)中查询了某条记录A(A.name = 1);然后调用method_B(T2事务,并且是REQUIRES_NEW  )

2、在 method_B中修改了记录A并提交保存(A.name = 2);(method_B方法结束,T2事务提交)

3、然后回到 method_A  中再次查询这条记录A,发现得到的A.name = 1;但是此时数据库中的A.name = 2 。

用hibernate/mybatis得到的都是以上结果, 即在T1中查到的A.name = 1.

但是,我用spring的JdbcTemplate测试却发现: 本来在(3)得到A.name=1,但实际A.name =2。

  为什么mybatis&hibernate得到的结果与JdbcTemplate不一样了?事务不是统一交给spring控制的吗?

(见问题: Spring事务REQUIRES_NEW的问题?)

个人理解

  最初, 我以为在(3)一定会得到是A.name = 2。但实际在hibernate中得到的是A.name =1。(当时遇到问题用的是hibernate。)

  然后我就重新去理解了REQUIRES_NEW, 发现应该是要得到A.name = 1, 即mybatis&hibernate得到的就是正确的。

  但无意用JdbcTemplate测试却发现和mybatis&hibernate得到的不一样, 所以就迷茫了。完全不知道怎么理解。

  现在在想一想, 到底什么是"事务控制"? 其实现在我也不知道怎么理解, 渣狗一只, 汪汪~~

  可以参考:

    spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!

    spring事务源码解析 (这个可以细看)

  但为什么觉得mybatis&hibernate的结果更正确呢?

    1、更能体现出事务的一致性。

      因为对t1事务来说,并没有改变过A.name。所以,从始至终都应该得到A.name =1。

一、spring boot公共部分

@SpringBootApplication
public class TransactionApplication {
    public final static String ID = "1";

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(TransactionApplication.class);
        app.run(args);
    }
}
TransactionApplication.java

相关文章: