spring源码分析——事务的传播机制

 

 

1:REQUIRED(默认),如果不配置传播属性,默认就是required属性,如果当前有事务就加入加入该事务 ,如果没有就新创建一个事务

准备两个类,TestOuterService  ,TestInnerService,传播属性都是required的

在TestOutService中调用testInnerService的方法:

 

 

 看看运行结果:抛出异常,数据没有插入,回滚成功

 

 

看看源码是否使用了TestOuterService的事务,而把TestInnerService的事务挂起

 

 

 

 

 

 

 

 

不是新事务,所以跳过回滚

 

 

 

 

 

 

 

 

 

 

 

 

 

 

所以如果外层事务和内层事务都是required的机制的话,会把内层事务挂起,加入到外层事务。

 

如果把外层事务去掉会怎么样?

 

 

 运行结果显示:抛出异常,数据没有插入,回滚正常。

 

 

我们看一下事务拦截器:

因为TestOuterService没有事务注解配置,所有没有被代理,不会进入事务拦截器,当调用到TestInnerService的时候才会进入事务切面

 

 

 

 

 

 

 

 

如果内存和外层的事务都开启,相当于只用外层的事务,内层的事务挂起。

 

2:Supports,支持使用当前事务,如果当前事务不存在,则不适用事务

 

 

 

 

 

 

 从运行结果看:抛出异常,数据插入,说明事务没有生效

 

看一下拦截器如果工作:

 

 

 当前没有事务,所以不会进入回滚逻辑:

 

 

 

 

 

 

如果把外层的事务放开,再运行一下:

 

 

 

 结果显示,存在事务,数据没有插入,所以supports这个事务看起来和没有注解@Transactional,效果一样。

 

3:REQUIRES_NEW  创建一个新事务,当前事务存在,就挂起当前事务

TestOuterService类,事务级别为required

 

 

 

 

 

 

运行结果:抛出异常,数据没有插入,回滚正常。

我们从拦截器中看一下工作原理:

内层事务调用抛出异常:

 

 

 

 

 

 内层调用有事务存在,同时是个新事务,所以会回滚

 

外层事务,如果抛出异常,也会回滚:

 

 

 

所以required_new 是创建一个新事务,即使外层有事务存在,还是用自己的事务。

 

4:NOT_SUPPORTS   不支持事务,如果当前有事务,就将事务挂起

 

 

 

 

运行结果:数据被插入,当前事务被挂起

 

 内层执行后,没有事务存在,同时也不是新事务。

 

5:MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception

 

 

 

 

 运行结果:数据没有查询,有事务存在,回滚正常。

把外层的事务去掉后:

 

 

运行结果:,因为声明为mandatory类型,所以必须存在事务,否则就会抛异常

 

 

6:NEVER:无事务执行,如果当前有事务则抛出Exception。

 

 

 

 运行结果:抛异常,因为标记传播属性为never,但是外层有事务存在

 

 

7:NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样

 

总结:

required  和 required_new 一个是当前存在事务就加入,挂起自己的事务;另一个是创建一个新的事务,如果存在事务,挂起存在的事务

supports 和 not_supports 一个是支持当前事务,有就加入,没有则不使用事务;另一个是不支持事务,当前存在事务则挂起

mandatroy 和 never  一个是强势使用事务,没有则抛异常; 一个是不使用事务,有则抛异常

nested:存在就嵌套使用,当前不存在就等同于required的

 

posted @ 2020-07-08 16:10  程序员三藏  阅读(904)  评论(0编辑  收藏  举报