theme: channing-cyan
这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
一、事务的传播行为
概念
- spring支持7种事务传播行为,确定客户端和被调用端的事务边界
- 多个具有事务控制的service的相互调用时所形成的复杂的事务边界控制
- 事务的传播行为是Spring框架独有的事务增强特性,它不属于事务实际提供方数据库行为
分类
外围方法事务
外围方法抛出异常,这两种方法的事务都会被回滚
- NESTED
- REQUIRED
- REQUIRED是加入外围方法事务,所以和外围事务同属于一个事务,一旦REQUIRED事务抛出异常被回滚,外围方法事务也将被回滚。而NESTED是外围方法的子事务,有单独的保存点,所以NESTED方法抛出异常被回滚,不会影响到外围方法的事务。
内部方法事务
内部方法事务回滚而不影响外围方法事务
- NESTED
- REQUIRES_NEW
- NESTED是嵌套事务,所以外围方法回滚之后,作为外围方法事务的子事务也会被回滚。而REQUIRES_NEW是通过开启新的事务实现的,内部事务和外围事务是两个事务,外围事务回滚不会影响内部事务
二、事务错误使用异常场景
场景,执行带事务的语句时,报以下的错误。
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
代码如下 :
分析
methodA与methodB共用一个事务,methodB将事务标志为回滚,methodA中commit这个事务,然后,出现事务已经被标志回滚(methodB标志的)的异常信息。
解决方案
- methodA与methodB在逻辑上不应该属于同一个事务,那么将methodB的事务传播属性修改为PROPAGATIONREQUIRESNEW,这样,执行methodB时,会创建一个新的事务,不影响methodA中的事务
- 业务A与业务B在业务逻辑上就应该属于同一个事务,那么将methodA中的try catch去掉
- methodB的失败与否不能影响methodA的事务提交,将methodB的事务传播特性修改成PROPAGATION_NESTED,即失败不影响外部事务,成功则和外部事务一起提交。