Spring事务传播机制,多个事务方法互相调用时,事务如何在这些方法间传播

方法A 是一个事务的方法,方法A 执行过程中调用了方法B,那么方法B 有无事务以及方法B 对事务的要求不同都会对方法A的事务具体执行造成影响,同时方法A的事务对方法B 的事务执行也有影响,这种影响力具体什么就有两个方法所定义的事务传播类型所决定。

 这些参数都是修饰被调用者,就是下面说的b

  • REQUIRED (spring 默认的事务传播机制):如果当前(调用方)没有事务,则自己(被调用放)新建一个事务,如果当前存在事务,则加入这个事务。

比如 a 方法 调用 b ,如果a 没有事务,b 就新建一个事务。 如果a 有事务(2条sql),b也有事务(2条ssql),那么就是4条sql,组成一个事务,要么同时成功,要么同时回滚。

  • SUPPORTS : 当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行。

如果A有事务,b就加入进来,都以事务方式进行运行。如果a没有事务,b也不要事务,大家都以非事务的方式进行运行。

  • MANDATORY : 当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
  • REQUIRED_NEW : 创建一个新事务,如果存在当前事务,则挂起该事务。

挂起事务:a里面他已经有事务,b就要把A 的事务挂起,b就自己以事务方式运行,说白了就是a自己处理自己的事务,b自己处理自己的事务。大家各自互相不干扰。

  • NOT_SUPPORTS :以非事务方式执行,如果当前存在事务,则挂起该事务。
  • NEVER:不使用事务,如果当前事务存在,则抛出异常。

不能存在事务,a如果有事务,我就抛异常

  • NESTED:如果当前事务存在,则在嵌套事务中执行,否则REQUIRED 的操作一样(开启一个事务)

嵌套事务:在a调用b 的时候,a要是没有事务,b自己开启了一个事务, a要是有事务,b 就嵌套在里面。嵌套就是一个父事务,一个子事务,a 是父事务,b 是子事务。

  • NESTED 和 REQUIRED_NEW 的区别:

REQUIRED_NEW 是新建一个事务并且新开启的这个事务与原有事务无关,而NESTED 则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务),在NESTED 情况下父事回滚时,子事务也会回滚,而在REQUIRED_NEW 情况下,原有事务回滚,不会影响新开的事务。

  • NESTED 和REQUIRED 的区别:

REQUIRED 情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用放出现异常时,由于共用一个事务,所以无论调用方是否catch 其异常,事务都会回滚,而在NESTED 情况下,被调用方发生异常时,调用放可以catch 其异常,这样只有子事务回滚,父事务不受影响。

spring 事务什么时候会失效

通常使用@Transactional来实现, 实际上spring 会在底层帮我们开启一个代理对象,代理对象的机制其实就是aop的机制。aop 的缺陷会使事务失效。

spring 事务的原理是aop,进行了切面增强,那么失效的根本原因是这个aop不起作用了,常见情况如下几种:

1、发生自调用,类里面使用this调用本来的方法(this 通常省略),此时这个this对象不是getbean

里面的代理对象,而是userService 对象本身!

解决方法:全部使用@Autowired去调用。

2、方法不是public的

@Transactional 只能用于public 的方法上,否则事务会失效。如果要用在非public 方法上,可以开启AspectJ 代理模式。

3、数据库本身不支持事务。

4、没有被spring 管理。(方法上加了@Transactional,但是类并没有交给spring去管理,比如没有@service ,@compent)

5、异常被吃掉(try-cath),事务不会回滚(或者抛出的异常没有被定义,默认为RuntimeException);

你可能感兴趣的:(java,开发语言)