Spring事务传播机制以及事务嵌套

  • Spring事务传播机制
  • 事务嵌套场景
    • 情景0:
    • 场景1:不同类中,开启事务的方法调用没有开启事务的方法
    • 场景2:不同类中,methodA方法嵌套methodB方法,且传播机制不同
    • 场景3:不同类中,NESTED传播机制的效果
    • 场景4:不同类中,没有开启事务的方法调用开启事务的方法
    • 情景5:同一个类中,methodA未开启事务,methodB开启事务
    • 情景6:同一个类中,methodA开启事务,methodB未开启事务

Spring事务传播机制

Spring 通过切面配置事务传播机制 PROPAGATION

  1. 默认 REQUIRED 支持当前事务,当前没有事务则新建

  2. REQUIRED_NEW 挂起当前事务,新建事务连接

  3. SUPPORTS 支持当前事务,如果没有,则以非事务方式执行(自动提交)

  4. MANDATORY 支持当前事务,如果没有,则抛出异常

  5. NOT_SUPPORTS 以非事务方式执行操作,如果当前事务存在,就把当前事务挂起

  6. NEVER 以非事务方式执行,如果存在事务,则抛出异常

  7. NESTED 实现事务分部分回滚

事务嵌套场景

默认发生的异常都是符合回滚条件的异常

情景0:

methodA开启事务@Transactional(propagation = Propagation.REQUIRED),写库前或者写库后发生异常,methodA都会发生回滚!

场景1:不同类中,开启事务的方法调用没有开启事务的方法

methodA方法嵌套methodB方法,其中methodA开启事务@Transactional(propagation = Propagation.REQUIRED),methodB方法没有添加事务注解:
● 情况1:(默认methodA中无异常发生)methodB方法抛出异常
methodA,methodB 会发生回滚
● 情况2:(默认methodA中无异常发生)methodB方法抛出异常,但是在methodA中将methodB抛出的异常try cache掉了,没有继续向外抛出

1、methodA不会发生回滚,
2、理论上methodB 也不会发生回滚,但是异常发生的位置会影响methodB写库操作是否能成功2.1、如果异常是在methodB写库后发生,则写库是成功的,且不会发生回滚2.2、如果异常是在methodB写库前发生,此时写库操作还未执行,此时数据未入库并不是因为发生了回滚,而是写库未执行造成的

● 情况3:在methodB执行前,methodA抛出异常

1、methodA发生回滚
2、理论上methodB也会发生回滚,此时methodB未执行

● 情况4:在methodB执行后,methodA抛出异常

1、methodA发生回滚
2、methodB发生回滚

此种情景methodA,methodB属于一个事务连接

场景2:不同类中,methodA方法嵌套methodB方法,且传播机制不同

methodA方法嵌套methodB方法,其中methodA开启事务@Transactional(propagation = Propagation.REQUIRED),methodB方法添加事务注解@Transactional(propagation = Propagation.REQUIRES_NEW):
● 情况1:(默认methodA中无异常发生) methodB方法抛出异常

1、methodA发生回滚,因为methodB发生异常导致
2、methodB发生回滚

● 情况2:(默认methodA中无异常发生) methodB方法抛出异常,但是在methodA中将methodB抛出的异常try cache掉了,没有继续向外抛出

1、methodA写库成功
2、methodB发生回滚

● 情况3:在methodB执行前,methodA抛出异常

1、methodA发生回滚
2、理论上methodB不会发生回滚,此时methodB未执行

● 情况4:在methodB执行后,methodA抛出异常

1、methodA发生回滚
2、理论上methodB不会发生回滚

此种情景methodA,methodB属于不同的事务连接,执行methodB的事务时,会将methodA的事务挂起。

场景3:不同类中,NESTED传播机制的效果

methodA方法嵌套methodB方法,其中methodA开启事务@Transactional(propagation = Propagation.REQUIRED),methodB方法添加事务注解@Transactional(propagation = Propagation.NESTED)
,methodB方法添加事务注解@Transactional(propagation = Propagation.NESTED)


classA中
@Transactional(propagation = Propagation.REQUIRED)
public void methodA(){try{classB.methodB();}catch(Exception e){classB.methodC();}}classB中
@Transactional(propagation = Propagation.NESTED)
public void methodB(){}classB中
@Transactional(propagation = Propagation.NESTED)
public void methodC(){}
methodA在执行methodB前会保存一个savePoint,
当methodB发生异常时,会回滚到savePoint,然后再去执行后续的代码  完善了情景1-情况2中的问题

此种情景methodA,methodB,methodC属于同一个事务连接,该事务具备部分回滚的能力

场景4:不同类中,没有开启事务的方法调用开启事务的方法

methodA方法嵌套methodB方法,其中methodA不开启事务,methodB方法添加事务注解@Transactional(propagation = Propagation.REQUIRED):

  • 情况1:methodB发生异常
1、methodA不回滚
2、methodB会回滚
  • 情况2:methodA发生异常
1、methodA不回滚
2、methodB不回滚

问题:
1、情景1-情况2中,如果methodB也添加@Transactional(propagation = Propagation.REQUIRED),则methodB,methodA都发生回滚

注:情景1-情景4 methodA,methodB在不同的类中

情景5:同一个类中,methodA未开启事务,methodB开启事务

  • 情况1:methodA或methodB发生异常
 public void methodA() {OssTask taskCc = new OssTask().setName("testa");taskCc.setProjectId("2");taskService.save(taskCc);methodB();}@Transactional(propagation = Propagation.REQUIRED)public void methodB() {OssTask taskCc = new OssTask().setName("testb");taskCc.setProjectId("3");taskService.save(taskCc);int w = 2/0;  // 抛出异常}

结果:

methodA,methodB 都未发生回滚

  • 情况2:methodB发生异常,但是methodA通过代理类调用methodB
 public void methodA() {OssTask taskCc = new OssTask().setName("testa");taskCc.setProjectId("2");taskService.save(taskCc);ModuleServiceImpl moduleService = (ModuleServiceImpl) AopContext.currentProxy();moduleService.methodB();}@Transactional(propagation = Propagation.REQUIRED)public void methodB() {OssTask taskCc = new OssTask().setName("testb");taskCc.setProjectId("3");taskService.save(taskCc);int w = 2/0;}

此时methodB中事务发生回滚,methodA中无事务所以不发生回滚

情景6:同一个类中,methodA开启事务,methodB未开启事务

  • 情况1:methodB发生异常
 @Transactional(propagation = Propagation.REQUIRED)public void methodA() {OssTask taskCc = new OssTask().setName("testa");taskCc.setProjectId("2");taskService.save(taskCc);methodB();}//    @Transactional(propagation = Propagation.REQUIRED)public void methodB() {OssTask taskCc = new OssTask().setName("testb");taskCc.setProjectId("3");taskService.save(taskCc);int w = 2/0;}

methodA,methodB 发生回滚

  • 情况2:methodA发生异常
 @Transactional(propagation = Propagation.REQUIRED)public void methodA() {OssTask taskCc = new OssTask().setName("testa");taskCc.setProjectId("2");taskService.save(taskCc);methodB();int w = 2/0;}//    @Transactional(propagation = Propagation.REQUIRED)public void methodB() {OssTask taskCc = new OssTask().setName("testb");taskCc.setProjectId("3");taskService.save(taskCc);}

同上,发生回滚

综合情景5和情景6:
Spring的声明式事务是基于Aop实现的,将业务逻辑和事务逻辑进行解耦,在Aop的代理下,只有目标方法通过外部调用,目标方法才有代理对象来进行管理,反之如果是内部调用,目标方法还是由原对象管理,此时改方法并没有得到增强处理,也就是会造成自调用问题(事务失效)。
重点在于,Spring采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。
而在同一个class中,方法A调用方法B,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用,也就无法通过注解保证事务性了。
也就是说,在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用。

Spring事务传播机制以及事务嵌套相关推荐

  1. Spring事务与事务传播机制

    目录 1.事务的基本概念 2.Spring事务的实现 3.事务隔离级别 4.事务传播机制 1.事务的基本概念 关于事务的一些基础概念我已经在MYSQL中讲解过了,有不了解的可以移步至此篇文章: MyS ...

  2. 【Spring事务】事务和事务传播机制

    事务 事务主要有三种操作: 开始事务 start transaction 提交事务 commit 回滚事务 rollback Spring 中事务的实现 Spring 中的事务操作分为两类: ⼿动操作 ...

  3. JavaEE进阶 - Spring事务和事务传播机制 - 细节狂魔

    文章目录 1.为什么需要事务?(回顾) 2.Spring 中事务的实现 MySQL 中的事务使用(回顾) 1.⼿动操作事务(编程式事务) 2. 声明式事务(利用注解自动开启和提交事务) @Transa ...

  4. spring上下文是什么意思_Java程序员只会CRUD连Spring事务传播机制都不懂?

    AQS到底有什么用?难道就真的只是为了面试吗? 当然不是说AQS没用,如果你不是做基础架构或者中间件开发,你很难感受到AQS的威力.当然,学习很多时候,需要的是正向反馈,学了太多造火箭的东西,面试完就 ...

  5. 原创 | CRUD更要知道的Spring事务传播机制

    来自:肥朝 AQS到底有什么用?难道就真的只是为了面试吗? 当然不是说AQS没用,如果你不是做基础架构或者中间件开发,你很难感受到AQS的威力.当然,学习很多时候,需要的是正向反馈,学了太多造火箭的东 ...

  6. Spring事务传播机制和隔离级别

    Spring有5种隔离级别,7种传播行为.这是面试常问的内容,也是代码中经常碰到的知识点.这些知识枯燥而且乏味,其中有些非常的绕.如果栽在这上面,就实在是太可惜了. @Transactional(is ...

  7. java spring 事务传播_spring事务传播机制实例讲解

    天温习spring的事务处理机制,总结如下 对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011 spri ...

  8. Spring 事务传播机制 实例讲解

    事务传播机制 对于SQL事务的概念以及ACID性质,可以参见我的另一篇博文 http://kingj.iteye.com/admin/blogs/1675011 spring的管理的事务可以分为如下2 ...

  9. Spring的7种事务传播机制

    前言 什么是事务? 事务就是用户定义的一系列数据库操作,这些操作可以视为一个完成的逻辑处理工作单元,要么全部执行,要么全部不执行,是不可分割的工作单元.对数据库的增删改查操作 传播机制是什么? 当A调 ...

最新文章

  1. Linux下如何把时间转成秒数,或把秒数转换成标准时间
  2. oracle每一行的hash值,Hash分区表分区数与数据分布的测试
  3. OpenCV使用G-API的人脸分析管道
  4. Rendering: repaint, reflow/relayout, restyle的学习笔记
  5. android 蒙版图片带拖动_Android实现蒙版弹出框效果
  6. JavaScript四则运算的一些特殊情况
  7. 从 Poisson 分布到服务器的访问
  8. linux使用中的问题 --- (防火墙iptables -F)
  9. hex2text php,php如通过AES加密/解密实现bin2hex和hex2bin之间的切换
  10. 我的微信小程序登陆界面
  11. 30天敏捷结果(10):发挥你的优势
  12. 在Centos8编译Wireshark3.4.5
  13. matlab结构体、数组和单元数组类型的创建
  14. xslx-style导出,表头样式表格样式,指定条件
  15. 倒残差与线性瓶颈浅析 - MobileNetV2
  16. Microsoft Teams 创建Outlook邮件组的Team
  17. Java设计模式总结——6大设计原则
  18. 电脑突然连不上WiFi?按步骤检查
  19. 摩托车新手驾驶教程[2]
  20. HTML5页面背景切换

热门文章

  1. Ps(Adobephoto shop)中钢笔的一些简单的使用方法
  2. 基础java项目6( notic)
  3. 智能驾驶“国潮来袭”,“福瑞泰克+地平线”中国量产级组合亮相上海车展
  4. a标签点击中文文件名乱码_a 标签下载文件并解决中文乱码问题
  5. Arduino使用磁簧开关
  6. 我要写一篇关于酒店管理系统论文,请说一说酒店管理系统的研究背景
  7. kindeditor 上传图片失败问题总结
  8. 如何检测晶振是否合格?
  9. audio标签实现网页循环播放背景音乐代码实现
  10. java: 无法访问org.springframework.boot.SpringApplication ,错误的类文件:XXX,类文件具有错误的版本 61.0, 应为 52.0