以下所有表格中的Function1和Function2所使用的事务类型, 都对应上面标题加粗的那个类型
REQUIRED
@Transactional的默认类型
在外围方法未开启事务的情况下Propagation.REQUIRED注解的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
外围方法开启事务的情况下Propagation.REQUIRED注解的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围没有开启事务,调用的方法分别在独立的自己的事务内,外围方法抛出异常不会影响到调用方法的的事务,所以都能成功 |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 回滚 | 外围没有开启事务,调用的方法分别在独立的自己的事务内,方法2抛出异常只会回滚本身的事务。 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required,所以都会加入到外围事务,全部都会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required,所以都会加入到外围事务,全部都会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常; 外围方法捕获方法2的异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required,所以都会加入到外围事务,全部都会回滚,由于捕获了异常但是没有抛出,会报错: Transaction silently rolled back because it has been marked as rollback-only |
SUPPORTS
存在事务,就加入到事务中; 不存在事务,就不创建自己的事务。
在外围方法未开启事务的情况下,Propagation.SUPPORTS注解的的方法会以无事务的方式运行。
在外围方法开启事务的情况下,Propagation.SUPPORTS注解的方法会加入当前事务。
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围方法没有事务,内部的方法1,方法2以无事务的方式运行,所以抛出异常不会回滚 |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 成功 | 外围方法没有事务,内部的方法1,方法2以无事务的方式运行,所以抛出异常不会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 回滚 | 回滚 | 外围方法有事务,内部的方法1,方法2加入外围事务的方式运行,所以外围方法抛出异常会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 回滚 | 回滚 | 外围方法有事务,内部的方法1,方法2加入外围事务的方式运行,所以方法2抛出异常会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常; 外围方法捕获方法2的异常 | 回滚 | 回滚 | 外围方法有事务,内部的方法1,方法2加入外围事务的方式运行,所以方法2抛出异常会回滚; 由于捕获了异常但是没有抛出,会报错: Transaction silently rolled back because it has been marked as rollback-only |
MANDATORY
只能运行在一个已经存在的事务中,不能自己创建事务
在外围方法未开启事务的情况下,Propagation.MANDATORY注解的方法运行时会抛出错误:No existing transaction found for transaction marked with propagation 'mandatory'
在外围方法开启事务的情况下,Propagation.MANDATORY注解的方法会加入当前事务。
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 直接报错 | No existing transaction found for transaction marked with propagation 'mandatory' | |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 直接报错 | No existing transaction found for transaction marked with propagation 'mandatory' | |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是MANDATORY,2个方法会加入已有的外围创建的事务,外围方法的异常会导致方法1、方法2回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是MANDATORY,2个方法会加入已有的外围创建的事务,方法2的异常会导致方法1、方法2回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常; 外围方法捕获方法2的异常 | 回滚 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required_new,都会加入到新的的事务,所以方法1能成功,方法2抛出了异常就回滚了;由于捕获了异常但是没有抛出,会报错: Transaction silently rolled back because it has been marked as rollback-only |
REQUIRES_NEW
不管当前是否已经存在事务,都会新建一个事务
在外围方法未开启事务的情况下,Propagation.REQUIRES_NEW注解的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
在外围方法开启事务的情况下,Propagation.REQUIRES_NEW注解的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围没有开启事务,调用的方法分别在独立的自己的事务内,外围方法抛出异常不会影响到调用方法的的事务,所以都能成功 |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 回滚 | 外围没有开启事务,调用的方法分别在独立的自己的事务内,方法2抛出异常只会回滚本身的事务。 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required_new,都会加入到新的的事务,外围方法的异常不会影响方法1、方法2,所以都能成功 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required_new,都会加入到新的的事务,所以方法1能成功,方法2抛出了异异常就回滚了 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常; 外围方法捕获方法2的异常 | 成功 | 回滚 | 外围有开启事务,调用的方法分别在独立的自己的事务内,因为是required_new,都会加入到新的的事务,所以方法1能成功,方法2抛出了异常就回滚了;由于捕获了异常但是没有抛出,会报错: Transaction silently rolled back because it has been marked as rollback-only |
NOT_SUPPORTED
当前方法不应该有事务,如果有事务存在,将它挂起,以无事务状态运行
不管外围方法是否有事务,NOT_SUPPORT都会以无事务的方式运行
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
5个场景 | 成功 | 成功 | 不管外围方法是否有事务,内部的方法1,方法2都会以无事务的方式运行,所以抛出异常不会回滚 |
NEVER
注释的业务方法绝对不能在事务中运行,否则抛出异常
在外围方法未开启事务的情况下,Propagation.NEVER注解的内部方法会以无事务的方式运行。
在外围方法开启事务的情况下,Propagation.NEVER注解的内部方法会因为不能加入到事务中,抛出异常Existing transaction found for transaction marked with propagation 'never'
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围没有开启事务,调用的方法1,方法2都以无事务方式运行,外围方法抛出异常不会回滚 |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 成功 | 外围没有开启事务,调用的方法1,方法2都以无事务方式运行,方法2抛出异常不会回滚 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2 | 抛出异常 | 外围有开启事务,因为是NEVER,无法在已存在的事务中运行,会抛出和异常:Existing transaction found for transaction marked with propagation 'never' |
NESTED
**如果当前不存在事务,就按REQUIRED方式; 如果存在事务, 则开启一个 "嵌套" 事务, 它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. **
外围方法没有开启事务,Propagation.NESTED注解的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
外围方法开启事务,Propagation.NESTED注解的内部方法会在已存在的事务中开启一个子事务,抛出子事务的方法抛出异常可以被外围方法捕获,不会影响主事务; 而外围方法的主事务回滚却会导致子事务也会回滚(与requried不同的是:nested的异常被捕获了不会影响外层方法的事务。)。
当外围方法有事务的时候,运行会报错:JpaDialect does not support savepoints - check your JPA provider's capabilities
意思是通过jpa的方式不支持savepoints,
所以需要通过JdbcTemplte的方式运行
场景 | Function1 | Function2 | 解释 |
---|---|---|---|
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 成功 | 成功 | 外围没有事务,内部按照REQUIRED运行 |
外围方法没有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 成功 | 回滚 | 外围没有事务,内部按照REQUIRED运行; |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 外围方法抛出异常 | 回滚 | 回滚 | 外围方法的异常会回滚nested注解的事务 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常 | 回滚 | 回滚 | 方法2抛出异常回滚到该子事务设置的保存点,然后异常往上抛出到外层方法,所以导致方法1回滚了 |
外围方法有事务; 调用有事务的方法1; 调用有事务的方法2; 方法2抛出异常; 外围方法捕获方法2的异常 | 成功 | 回滚 | 方法2抛出异常只回滚到该子事务设置的保存点,然后异常抛出后被捕获了,所以不会影响外层方法和方法1的结果 |
网友评论