1. 所有传播行为
- REQUIRED(默认类型):
-
- 如果当前存在事务,则加入该事务;如果没有,则新建一个事务。
- 适用于大多数业务场景。
- SUPPORTS:
-
- 如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。
- 适合可选的事务场景。
- MANDATORY:
-
- 如果当前存在事务,则加入该事务;如果没有事务,则抛出异常。
- 用于必须在一个事务中执行的场景。
- REQUIRES_NEW:
-
- 创建一个新事务;如果当前存在事务,则挂起当前事务。
- 适用于需要与当前事务独立的情况。
- NOT_SUPPORTED:
-
- 以非事务方式执行;如果当前存在事务,则挂起当前事务。
- 适合不需要事务的执行场景。
- NEVER:
-
- 不使用事务;如果当前存在事务,则抛出异常。
- 用于明确不允许事务的场景。
- NESTED:
-
- 如果当前存在事务,则在嵌套事务中执行;否则与REQUIRED相同。
- 适用于需要支持部分回滚的场景。
2. REQUIRED,REQUIRES_NEW,NESTED异同
NESTED和REQUIRED修饰的内部方法都属于外围方法事务,如果外围方法抛出异常,这两种方法的事务都会被回滚。但是REQUIRED是加入外围方法事务,所以和外围事务同属于一个事务,一旦REQUIRED事务抛出异常被回滚,外围方法事务也将被回滚。而NESTED是外围方法的子事务,有单独的保存点,所以NESTED方法抛出异常被回滚,不会影响到外围方法的事务。
NESTED和REQUIRES_NEW都可以做到内部方法事务回滚而不影响外围方法事务。但是因为NESTED是嵌套事务,所以外围方法回滚之后,作为外围方法事务的子事务也会被回滚。而REQUIRES_NEW是通过开启新的事务实现的,内部事务和外围事务是两个事务,外围事务回滚不会影响内部事务。
3. 事务不生效的原因
spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不起作用了!常见情况有
如下几种
1、发生自调用,类里面使用this调用本类的方法(this通常省略),此时这个this对象不是代理类,而是
UserService对象本身!解决方法很简单,让那个this变成UserService的代理类即可!
2、方法不是public的:@Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在
非 public 方法上,可以开启 AspectJ 代理模式。
3、数据库不支持事务