经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
spring的事务传播机制
来源:cnblogs  作者:源灬点  时间:2023/4/24 8:57:25  对本文有异议

spring的事务传播机制

嫌弃内容代码复杂的可直接看思维导图大纲即可

基本概念

指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行

七种行为和测试

PROPAGATION_REQUIRED

默认,当前存在事务,则加入该事务;不存在事务,创建新事务。

  1. public class PropagationService {
  2. @Autowired
  3. private
  4. PropagationMapper propagationMapper;
  5. @Autowired
  6.     @Lazy
  7. PropagationService propagationService;
  8.     @Transactional(rollbackFor = Exception.class)
  9. public void insertPropagationA() throws Exception {
  10. Propagation propagationA = Propagation.builder()
  11. .type("Propagation.REQUIRED")
  12. .comment("propagationA").build();
  13. propagationMapper.insert(propagationA);
  14. propagationServiceSelf.insertPropagationB();
  15. throw new Exception();
  16. }
  17. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.REQUIRED)
  18. public void insertPropagationB() throws Exception {
  19. Propagation propagationB = Propagation.builder()
  20. .type("Propagation.REQUIRED")
  21. .comment("propagationB").build();
  22. Propagation propagationBB = Propagation.builder()
  23. .type("Propagation.REQUIRED")
  24. .comment("propagationBB").build();
  25. propagationMapper.insert(propagationB);
  26. propagationMapper.insert(prop
  1. @Test
  2. //Given A传播行为required 和B为required,WHE A发生异常,THEN A插入失败,B插入失败
  3. public void testRequired() throws Exception {
  4. propagationService.insertPropagationA();
  5. }

PROPAGATION_REQUIRED_NEW

始终以新的事务运行,当前存在事务,则挂起原事务;不存在事务,创建新事务

  1. @Test
  2. //Given 同样代码更改B为required_new, WHE A发生异常, THEN B插入成功,A插入失败
  3. public void testRequiredNew() throws Exception {
  4. propagationService.insertPropagationA();
  5. }

PROPAGATION_SUPPORTS

支持当前事务。当前存在事务,则支持该事务;不存在事务,以非事务方式执行

  1.     @Test
  2. //Given 更改B为required_supports, A不开启事物, WHE B发生异常, THEN A、B插入成功BB失败;A开启事物因为有异常发生全失败
  3. public void testRequiredSupports() throws Exception {
  4. propagationService.insertPropagationA();
  5. }
  1. //@Transactional(rollbackFor = Exception.class)
  2. public void insertPropagationA() throws Exception {
  3. Propagation propagationA = Propagation.builder()
  4. .type("Propagation.REQUIRED")
  5. .comment("propagationA").build();
  6. propagationMapper.insert(propagationA);
  7. propagationServiceSelf.insertPropagationB();
  8. throw new Exception();
  9. }
  10. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.SUPPORTS)
  11. public void insertPropagationB() throws Exception {
  12. Propagation propagationB = Propagation.builder()
  13. .type("Propagation.REQUIRED")
  14. .comment("propagationB").build();
  15. Propagation propagationBB = Propagation.builder()
  16. .type("Propagation.REQUIRED")
  17. .comment("propagationBB").build();
  18. propagationMapper.insert(propagationB);
  19. int a = 1/0;
  20. propagationMapper.insert(propagationBB);
  21. }

PROPAGATION_NO_SUPPORTED

非事务方式执行,当前存在事务,则挂起该事务

  1.     @Test
  2. //Given 更改B为required_not_supports, A开启事物, WHEN A发生异常, THEN A插入失败、B插入成功
  3. public void testRequiredNotSupports() throws Exception {
  4. propagationService.insertPropagationA();
  5. }
  1.     @Transactional(rollbackFor = Exception.class)
  2. public void insertPropagationA() throws Exception {
  3. Propagation propagationA = Propagation.builder()
  4. .type("Propagation.REQUIRED")
  5. .comment("propagationA").build();
  6. propagationMapper.insert(propagationA);
  7. propagationServiceSelf.insertPropagationB();
  8. throw new Exception();
  9. }
  10. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED)
  11. public void insertPropagationB() throws Exception {
  12. Propagation propagationB = Propagation.builder()
  13. .type("Propagation.REQUIRED")
  14. .comment("propagationB").build();
  15. Propagation propagationBB = Propagation.builder()
  16. .type("Propagation.REQUIRED")
  17. .comment("propagationBB").build();
  18. propagationMapper.insert(propagationB);
  19. propagationMapper.insert(propagationBB);
  20. }

PROPAGATION_NEVER

非事务方式执行,当前存在事务,则抛出异常();

org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'

  1. at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:413)
  1.     @Transactional(rollbackFor = Exception.class)
  2. public void insertPropagationA() throws Exception {
  3. Propagation propagationA = Propagation.builder()
  4. .type("Propagation.REQUIRED")
  5. .comment("propagationA").build();
  6. propagationMapper.insert(propagationA);
  7. propagationServiceSelf.insertPropagationB();
  8. //throw new Exception();
  9. }
  10. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NEVER)
  11. public void insertPropagationB() throws Exception {
  12. Propagation propagationB = Propagation.builder()
  13. .type("Propagation.REQUIRED")
  14. .comment("propagationB").build();
  15. Propagation propagationBB = Propagation.builder()
  16. .type("Propagation.REQUIRED")
  17. .comment("propagationBB").build();
  18. propagationMapper.insert(propagationB);
  19. propagationMapper.insert(propagationBB);
  20. }
  1.     @Test
  2. //Given 更改B为required_never, A开启事物, 调用方法B时报错
  3. public void testRequiredNever() throws Exception {
  4. propagationService.insertPropagationA();
  5. }

PROPAGATION_NESTED

当前存在事务,则嵌套在该事务下起新事务执行;不存在事务,创建新事务。

  1.     @Test
  2. //Given 更改B为required_nested, A开启事物, 调用方法B,后抛出异常,都失败;A开启事物,调用方法B,B抛出异常,A catch,A成功,B失败
  3. public void testRequiredNested() throws Exception {
  4. propagationService.insertPropagationA();
  5. }
  1. @Transactional(rollbackFor = Exception.class)
  2. public void insertPropagationA() throws Exception {
  3. Propagation propagationA = Propagation.builder()
  4. .type("Propagation.REQUIRED")
  5. .comment("propagationA").build();
  6. propagationMapper.insert(propagationA);
  7. try{
  8. propagationServiceSelf.insertPropagationB();
  9. }catch(Exception e){
  10. }
  11. }
  12. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NESTED)
  13. public void insertPropagationB() throws Exception {
  14. Propagation propagationB = Propagation.builder()
  15. .type("Propagation.REQUIRED")
  16. .comment("propagationB").build();
  17. Propagation propagationBB = Propagation.builder()
  18. .type("Propagation.REQUIRED")
  19. .comment("propagationBB").build();
  20. propagationMapper.insert(propagationB);
  21. int a = 1/0;
  22. propagationMapper.insert(propagationBB);
  23. }

PROPAGATION_MANDATORY

事务方式运行,当前不存在事务,则抛出异常

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

  1. at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:362)
  1. //@Transactional(rollbackFor = Exception.class)
  2. public void insertPropagationA() throws Exception {
  3. Propagation propagationA = Propagation.builder()
  4. .type("Propagation.REQUIRED")
  5. .comment("propagationA").build();
  6. propagationMapper.insert(propagationA);
  7. propagationServiceSelf.insertPropagationB();
  8. }
  9. @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.MANDATORY)
  10. public void insertPropagationB() throws Exception {
  11. Propagation propagationB = Propagation.builder()
  12. .type("Propagation.REQUIRED")
  13. .comment("propagationB").build();
  14. Propagation propagationBB = Propagation.builder()
  15. .type("Propagation.REQUIRED")
  16. .comment("propagationBB").build();
  17. propagationMapper.insert(propagationB);
  18. propagationMapper.insert(propagationBB);
  19. }
  1.     @Test
  2. //Given 更改B为required_mandatory, WHEN A不开启事物,调用方法B, THEN调用B抛出异常;
  3. public void testRequiredMandatory() throws Exception {
  4. propagationService.insertPropagationA();
  5. }

Transactional失效

spring的事物是基于AOP代理实现的,也就是说背@Transactional修饰的方法所在类会有一个代理类,通过这个代理类实现的。并且也需要底层数据库支持事物,还需要在同一个库中,多个方法运行调用需要在同一个线程中。基于这情况大概失效场景分为两部分

非代理类方向

  • 数据库引擎不支持索引如MyISAm

  • 数据源未配置事物管理器

  • 数据库分布式部署,需要Seata技术解决

  • 多线程,两个事务方法不在同一个线程

代理类方向

  • 类未交给spring,代理自然无法生成

  • 自身调用,相当于this,代理类未生效

  • 事务方法修饰如非public、final、static修饰导致不能被代理

  • 异常类型错误,声明式事务默认对runtimeException、Error才可以触发回滚

  • 对抛出的异常,catch后处理不当。如吞了异常。

  • 设置了错误的传播行为

原文链接:https://www.cnblogs.com/yuandian8/p/17347777.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号