@Transactional事务生效问题

栏目: Java · 发布时间: 5年前

内容简介:平时我们使用spring框架,不论是springmvcv还是springboot,springCloud,绝大多数情况我们都是在方法,或者直接在类上面加一个@Transactional,将事务交给spring替我们去管理,然后并没有具体分析一些情况,今天结合几个例子,结合源代码,使用伪代码解释一波。1.情况一情况一就是这样,main方法里面顺序调用AB两个方法,A方法不加事务注解,B方法加了事务注解。如果不了解@Transactional 事务的传播性,可能会回答:A成功插入,B插入失败,但是实际情况却是A

平时我们使用spring框架,不论是springmvcv还是springboot,springCloud,绝大多数情况我们都是在方法,或者直接在类上面加一个@Transactional,将事务交给spring替我们去管理,然后并没有具体分析一些情况,今天结合几个例子,结合源代码,使用伪代码解释一波。

1.情况一

service(){
       //方法A
       methodA(){
           insertA();
       }
       //方法B
       @Transactional
       methodB(){
           insertB();
           throw new RunTimeException("强制抛一个异常");
       }
       public void static main(String[] args){
           methodA();
           methodB();
       }
   }

情况一就是这样,main方法里面顺序调用AB两个方法,A方法不加事务注解,B方法加了事务注解。如果不了解@Transactional 事务的传播性,可能会回答:A成功插入,B插入失败,但是实际情况却是A,B均插入成功了。到底是什么原因呢?这里先简单介绍一下事务的6个传播属性:

PROPAGATION_REQUIRED : 支持当前事务,如果当前没有事务,就新建一个事务,这也是最常见的

PROPAGATION_SUPPORTS : 支持当前事务,如果当前没有事务,就以非事务的方式执行

PROPAGATION_MANDATORY: 支持当前事务,如果当前没有事务,就抛异常

PROPAGATION_REQUIRES_NEW:新建事务,如果当前事务存在,就把当前事务挂起

PROPAGATION_NOT_SUPPORTED:以非事务的方式执行,如果存在当前事务,就把当前事务挂起

PROPAGATION_NEVER: 以非事务的方式执行,如果当前存在事务,就抛异常

PROPAGATION_NESTED:如果存在当前事务,则在嵌套事务内执行,如果当前没有事务,则新建一个事务

前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。

研究源码,调试程序可以看到:

A没有事务管理,则线程内的connection 有个autoCommit = true

B得到事务的时候,由于事务的传播性依然生效, 得到的还是A方法的commit,其autoCommit = true,故而逐条 sql 进行提交,即A,B都会插入

下面我们来分析情况二:

serviceA(){
    methodA(){
        insertA();
    }
} 
serviceB(){
    @Transactional
    methodB(){
        insertB();
        throw new RuntimeExcption("强制抛出的异常");
    }
}
serviceC(){
    @Autowired
    private ServiceA serviceA;
    @Autowired
    private ServiceB serviceB;

    public void staic main(String[] args){
        serviceA.methodA();
        serviceB.methodB();
    }
}

情况二的主要代码和情况一一样,都是要调用methodA和methodB,但是结果却不同,情况二的正确结果是指挥插入A,而B会回滚,这是为什么呢?同样是在B方法上面加了事务注解....

其实大家都知道,spring的事务是交由cglib动态代理的,而动态代理对象产生的时机就非常重要了。再回到本例子:

A:在同一个service内部,事务之间嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务(因为shpring使用的是动态代理的方式来控制的事务,而动态代理最终都是要调用原始对象的,而原始对象在调用方法时,已存在代理对象,是不会再触发代理了!)

B:两个方法在不同的service里(即不同的对象,即代理对象也不是同一个),在ServiceC中,使用注入的方式将serviceA和serviceB注入,这样即使A没有使用事务,B也有自己的代理,会根据PROPAGATION_REQUIRED 而生成新的事务.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Tensorflow:实战Google深度学习框架

Tensorflow:实战Google深度学习框架

郑泽宇、顾思宇 / 电子工业出版社 / 2017-2-10 / 79

TensorFlow是谷歌2015年开源的主流深度学习框架,目前已在谷歌、优步(Uber)、京东、小米等科技公司广泛应用。《Tensorflow实战》为使用TensorFlow深度学习框架的入门参考书,旨在帮助读者以最快、最有效的方式上手TensorFlow和深度学习。书中省略了深度学习繁琐的数学模型推导,从实际应用问题出发,通过具体的TensorFlow样例程序介绍如何使用深度学习解决这些问题。......一起来看看 《Tensorflow:实战Google深度学习框架》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具