首页 > 其他分享 >Spring事务的传播行为

Spring事务的传播行为

时间:2023-07-26 15:22:40浏览次数:36  
标签:事务 ServiceB ServiceA methodA 传播 PROPAGATION methodB Spring

Spring事务的七种传播行为

首先举例事务的嵌套:

ServiceA {  
     void methodA() {
         ServiceB.methodB();
     }
}
  
ServiceB {   
     void methodB() {
         
     }
}
      

其中ServiceA#methodA(我们称之为外部事务),ServiceB#methodB(我们称之为内部事务)

一、PROPAGATION_REQUIRED(Spring默认,常用)

如果当前要执行的事务不在另外一个事务中,那么就新起一个事务。比如ServiceB.methodB的事务级别 定义为PROPAGATION_REQUIRED,那么当执行ServiceA.methodA的时候有两种情况:

  1. 如果ServiceA.methodA已经存在事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。这时只有外部事务并且他们是共用的,所以这时ServiceA.methodA或者ServiceB.methodB无论哪个发生异常methodA和methodB作为一个整体都将一起回滚。
  2. 如果ServiceA.methodA没有事务,ServiceB.methodB就会为自己分配一个事务。这样,在ServiceA.methodA中是没有事务控制的。只是在ServiceB.methodB内的任何地方出现异常,ServiceB.methodB将会被回滚,不会引起ServiceA.methodA的回滚。

二、PROPAGATION_REQUIRES_NEW(常用)

启动一个新的,不依赖于环境的 "内部" 事务。 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务,它拥有自己的隔离范围,自己的锁,等等。当内部事务开始执行时,外部事务将被挂起,内务事务结束后,外部事务才将继续执行。

比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务:

  1. 如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。
  2. 如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

三、PROPAGATION_NESTED(常用)

开始一个"嵌套的"事务,它是已经存在事务的一个真正的子事务。嵌套事务开始执行时,它将取得一个 savepoint。如果这个嵌套事务失败,我们将回滚到此savepoint。潜套事务是外部事务的一部分,只有外部事务结束后它才会被提交。

比如我们将ServiceA.methodA事务级别设置为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_NESTED,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint,等待ServiceB.methodB的事务完成以后,ServiceA.methodA的事务才继续执行。因为ServiceB.methodB是外部事务的子事务,那么

  1. ServiceB.methodB执行完成无异常,此时还未提交事务,如果ServiceA.methodA发生异常回滚,ServiceB.methodB也将回滚。
  2. 如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

他与PROPAGATION_REQUIRES_NEW的区别是:
PROPAGATION_REQUIRES_NEW完全是一个新事务它与外部事务相互独立,而 PROPAGATION_NESTED 则是外部事务的子事务,如果外部事务 commit, 嵌套事务也会被 commit,这个规则同样适用于 roll back。

在Spring中使用PROPAGATION_NESTED的前提条件:

  1. TransactionManager中的nestedTransactionAllowed属性必须是true;
  2. JKD版本为1.4+,因为需要SavePoint类;
  3. JDBC Driver必须支持JDBC3.0。

四、PROPAGATION_SUPPORTS

如果当前运行的代码包含在事务中,就以事务的方式运行,如果不在一个事务中,就以非事务的方式运行。

五、PROPAGATION_NOT_SUPPORTED

表示当前不支持事务。例如传播属性为PROPAGATION_REQUIRED的外部事务ServiceA.methodA,而ServiceB.methodB为内部事务,它的传播属性为PROPAGATION_NOT_SUPPORTED,当运行到ServiceB.methodB的时候ServiceA.methodA的事务将被挂起,待ServiceB.methodB以非事务的方式运行完以后,再来执行ServiceA.methodA的事务。

六、PROPAGATION_MANDATORY

必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。

七、PROPAGATION_NEVER

不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。

标签:事务,ServiceB,ServiceA,methodA,传播,PROPAGATION,methodB,Spring
From: https://www.cnblogs.com/zhangjianbing/p/17582554.html

相关文章

  • 【Java面试题】Spring是如何解决循环依赖问题?
    ......
  • 【项目实战】Kafka 生产者幂等性和事务
    ......
  • Spring 中的 @Cacheable 缓存注解,太好用了!
    1什么是缓存第一个问题,首先要搞明白什么是缓存,缓存的意义是什么。对于普通业务,如果要查询一个数据,一般直接select数据库进行查找。但是在高流量的情况下,直接查找数据库就会成为性能的瓶颈。因为数据库查找的流程是先要从磁盘拿到数据,再刷新到内存,再返回数据。磁盘相比于内存来......
  • SpringBoot中定时任务开启多线程避免多任务堵塞
    场景SpringBoot中定时任务与异步定时任务的实现:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/117083609使用SpringBoot原生方式实现定时任务,已经开启多线程支持,以上是方式之一。除此之外还可通过如下方式。为什么SpringBoot定时任务是单线程的?查看注解@Ena......
  • 一次性打包学透 Spring
    不知从何时开始,Spring这个词开始频繁地出现在Java服务端开发者的日常工作中,很多Java开发者从工作的第一天开始就在使用SpringFramework,甚至有人调侃“不会Spring都不好意思自称是个Java开发者”。之所以出现这种局面,源于Spring是一个极为优秀的一站式集成框架,对Java......
  • Spring Boot 实现文件断点下载,实战来了!
    来源:juejin.cn/post/7026372482110079012前言互联网的连接速度慢且不稳定,有可能由于网络故障导致断开连接。在客户端下载一个大对象时,因网络断开导致上传下载失败的概率就会变得不可忽视。客户端在GET对象请求时通过设置Range头部来告诉接口服务需要从什么位置开始输出对象......
  • spring启动流程 (6完结) springmvc启动流程
    SpringMVC的启动入口在SpringServletContainerInitializer类,它是ServletContainerInitializer实现类(Servlet3.0新特性)。在实现方法中使用WebApplicationInitializer创建ApplicationContext、创建注册DispatcherServlet、初始化ApplicationContext等。SpringMVC已经将大部分的启......
  • 你真正了解Spring的工作原理吗
     Spring  1.1什么是SpringIOC和DI?  ①控制反转(IOC):Spring容器使用了工厂模式为我们创建了所需要的对象,我们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控制反转的思想。②依赖注入(DI):Spring使用JavaBean对象的Set方法或者带参数的构造方法......
  • SpringBoot+Prometheus+Grafana实现系统可视化监控
    场景SpringBoot中集成Actuator实现监控系统运行状态:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/124272494基于以上Actuator实现系统监控,还可采用如下方案。PrometheusPrometheus,是一个开源的系统监控和告警的工具包,其采用Pull方式采集时间序列的度量数据(也......
  • 我开源了团队内部基于SpringBoot Web快速开发的API脚手架v1.6.0更新
    什么是rest-api-spring-boot-starterrest-api-spring-boot-starter适用于SpringBootWebAPI快速构建让开发人员快速构建统一规范的业务RestFullAPI不在去关心一些繁琐。重复工作,而是把重点聚焦到业务。动机每次WebAPI常用功能都需要重新写一遍。或者复制之前的项目代码......