@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 而生成新的事务.


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

查看所有标签

猜你喜欢:

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

Blockchain Basics

Blockchain Basics

Daniel Drescher / Apress / 2017-3-16 / USD 20.99

In 25 concise steps, you will learn the basics of blockchain technology. No mathematical formulas, program code, or computer science jargon are used. No previous knowledge in computer science, mathema......一起来看看 《Blockchain Basics》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

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

HSV CMYK互换工具