spring的事务传播机制
2023/4/24 1:22:07
本文主要是介绍spring的事务传播机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
spring的事务传播机制
嫌弃内容代码复杂的可直接看思维导图大纲即可
基本概念
指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行
七种行为和测试
PROPAGATION_REQUIRED
默认,当前存在事务,则加入该事务;不存在事务,创建新事务。
public class PropagationService { @Autowired private PropagationMapper propagationMapper; @Autowired @Lazy PropagationService propagationService; @Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); propagationServiceSelf.insertPropagationB(); throw new Exception(); } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.REQUIRED) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); propagationMapper.insert(prop
@Test //Given A传播行为required 和B为required,WHE A发生异常,THEN A插入失败,B插入失败 public void testRequired() throws Exception { propagationService.insertPropagationA(); }
PROPAGATION_REQUIRED_NEW
始终以新的事务运行,当前存在事务,则挂起原事务;不存在事务,创建新事务
@Test //Given 同样代码更改B为required_new, WHE A发生异常, THEN B插入成功,A插入失败 public void testRequiredNew() throws Exception { propagationService.insertPropagationA(); }
PROPAGATION_SUPPORTS
支持当前事务。当前存在事务,则支持该事务;不存在事务,以非事务方式执行
@Test //Given 更改B为required_supports, A不开启事物, WHE B发生异常, THEN A、B插入成功BB失败;A开启事物因为有异常发生全失败 public void testRequiredSupports() throws Exception { propagationService.insertPropagationA(); }
//@Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); propagationServiceSelf.insertPropagationB(); throw new Exception(); } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.SUPPORTS) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); int a = 1/0; propagationMapper.insert(propagationBB); }
PROPAGATION_NO_SUPPORTED
非事务方式执行,当前存在事务,则挂起该事务
@Test //Given 更改B为required_not_supports, A开启事物, WHEN A发生异常, THEN A插入失败、B插入成功 public void testRequiredNotSupports() throws Exception { propagationService.insertPropagationA(); }
@Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); propagationServiceSelf.insertPropagationB(); throw new Exception(); } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); propagationMapper.insert(propagationBB); }
PROPAGATION_NEVER
非事务方式执行,当前存在事务,则抛出异常();
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:413)
@Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); propagationServiceSelf.insertPropagationB(); //throw new Exception(); } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NEVER) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); propagationMapper.insert(propagationBB); }
@Test //Given 更改B为required_never, A开启事物, 调用方法B时报错 public void testRequiredNever() throws Exception { propagationService.insertPropagationA(); }
PROPAGATION_NESTED
当前存在事务,则嵌套在该事务下起新事务执行;不存在事务,创建新事务。
@Test //Given 更改B为required_nested, A开启事物, 调用方法B,后抛出异常,都失败;A开启事物,调用方法B,B抛出异常,A catch,A成功,B失败 public void testRequiredNested() throws Exception { propagationService.insertPropagationA(); }
@Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); try{ propagationServiceSelf.insertPropagationB(); }catch(Exception e){ } } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NESTED) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); int a = 1/0; propagationMapper.insert(propagationBB); }
PROPAGATION_MANDATORY
事务方式运行,当前不存在事务,则抛出异常
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:362)
//@Transactional(rollbackFor = Exception.class) public void insertPropagationA() throws Exception { Propagation propagationA = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationA").build(); propagationMapper.insert(propagationA); propagationServiceSelf.insertPropagationB(); } @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.MANDATORY) public void insertPropagationB() throws Exception { Propagation propagationB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationB").build(); Propagation propagationBB = Propagation.builder() .type("Propagation.REQUIRED") .comment("propagationBB").build(); propagationMapper.insert(propagationB); propagationMapper.insert(propagationBB); }
@Test //Given 更改B为required_mandatory, WHEN A不开启事物,调用方法B, THEN调用B抛出异常; public void testRequiredMandatory() throws Exception { propagationService.insertPropagationA(); }
Transactional失效
spring的事物是基于AOP代理实现的,也就是说背@Transactional修饰的方法所在类会有一个代理类,通过这个代理类实现的。并且也需要底层数据库支持事物,还需要在同一个库中,多个方法运行调用需要在同一个线程中。基于这情况大概失效场景分为两部分
非代理类方向
-
数据库引擎不支持索引如MyISAm
-
数据源未配置事物管理器
-
数据库分布式部署,需要Seata技术解决
-
多线程,两个事务方法不在同一个线程
代理类方向
-
类未交给spring,代理自然无法生成
-
自身调用,相当于this,代理类未生效
-
事务方法修饰如非public、final、static修饰导致不能被代理
-
异常类型错误,声明式事务默认对runtimeException、Error才可以触发回滚
-
对抛出的异常,catch后处理不当。如吞了异常。
-
设置了错误的传播行为
这篇关于spring的事务传播机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15鸿蒙生态设备数量超8亿台
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?