【spring事务前置知识】事务的七大传播行为

el/2023/12/3 2:42:21

文章目录

  • 1 简介
  • 2 稍微更细致的介绍
    • 2.1 第2、3、4种请自行验证
    • 2.2 REQUIRES_NEW ---> 父级异常,它可正常提交
    • 2.3 PROPAGATION_NESTED ---> 父级异常,它必然回滚;它异常,父级可以不回滚
    • 2.4 PROPAGATION_NESTED和PROPAGATION_REQUIRED的区别
    • 2.5 PROPAGATION_NESTED和REQUIRES_NEW的区别


1 简介

事务传播行为是什么???为啥会有事务传播行为???这个问题我觉得其实挺好回答的。

假设方法A调用方法B

  • 方法A有事务,方法B可以什么不用管,直接拥有事务吗???
  • 方法A有事务,方法B可以不使用事务吗?—> 也就是说方法B虽然报异常了,但方法B仍然可以将数据插入到数据库里?
  • 方法A有事务,方法B可以有自己单独的事务吗? —> 比如方法B报异常了,只会导致方法B回滚,方法A不用回滚。
    。。。。。

真实工作中需求总是千变万化,上面这些类似的需求说不定哪天我们就真的会遇到,其实这就是所谓的事务传播行为,spring确实是真优秀,人家不仅想到了类似的需求,还一下想到了7种 — 即7大传播行为。7大传播行为总结如下:
在这里插入图片描述


2 稍微更细致的介绍

2.1 第2、3、4种请自行验证

上图中第2、3、4种事务传播行为没有啥,有兴趣的可以clone下来我的代码自己测试一下。

github地址:https://github.com/nieandsun/spring-study


PROPAGATION_NEVER 和 PROPAGATION_NOT_SUPPORTED也比较简单,这里简单再提一下:

  • PROPAGATION_NEVER —> 如果方法A存在事务,方法A调用方法B,方法B为强制非事务,方法A调用了方法B,方法A会直接报错,并发生回滚。

  • PROPAGATION_NOT_SUPPORTED —> 如果方法A存在事务,方法A调用方法B,方法B为不支持事务 ,则方法B报异常,会导致方法A回滚,但是方法B有可能会对数据库里的数据完成修改


2.2 REQUIRES_NEW —> 父级异常,它可正常提交

方法A存在事务,方法A(这里将方法A称为父级方法)调用方法B,方法B为REQUIRES_NEW时,方法B会新建一个新的事务,而不用方法A的事务,这样如果方法B没有异常,方法A调完方法B,方法A又报了异常,只会导致方法A进行回滚,而方法B可正常提交。


2.3 PROPAGATION_NESTED —> 父级异常,它必然回滚;它异常,父级可以不回滚

如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作很好理解。

如果当前存在事务,则在嵌套事务内执行,具体表现行为:

  • 如果方法A(这里将方法A称为父级方法)存在事务,且方法A调用方法B,方法B为PROPAGATION_NESTED 时,A方法可以捕获B方法的异常,从而只让B方法发生回滚,而A不发生回滚。
  • 并且假如方法A有事务,只要方法A发生了异常,方法B也肯定会回滚。

2.4 PROPAGATION_NESTED和PROPAGATION_REQUIRED的区别

以如下代码为例:

  • UserServiceImpl中的方法
@Transactional(rollbackFor = Exception.class)
@Override
public void addUserAndSalary(String username, BigDecimal salary) {//按照生日等生成一个14位的员工编号String account = "20191218000001";//往员工表里插入该用户的用户信息userServiceDao.saveUserInfo(username, account);//往人资表里插入该用户的工资信息try {salaryService.addSalaryInfo(account, salary);System.err.println(111);}catch (Exception e){e.printStackTrace();}//int i = 1 / 0;
}
  • SalaryServiceImpl中的方法
@Transactional(propagation = Propagation.XXXX, rollbackFor = Exception.class)
@Override
public void addSalaryInfo(String account, BigDecimal salary) {salaryDao.addSalaryInfo(account, salary);int i = 1 / 0;
}

如果addSalaryInfo方法标注的是PROPAGATION_NESTED时

  • 子级方法会发生回滚 —>salary表里无法插入数据
  • 父级方法会执行成功 —> user表里会插入数据

如果addSalaryInfo方法标注的是PROPAGATION_REQUIRED时

  • 子级方法会发生回滚 —>salary表里无法插入数据
  • 父级方法也会发生回滚 —>user表里无法插入数据

2.5 PROPAGATION_NESTED和REQUIRES_NEW的区别

以如下代码为例:

  • UserServiceImpl中的方法
    @Transactional(rollbackFor = Exception.class)@Overridepublic void addUserAndSalary(String username, BigDecimal salary) {//按照生日等生成一个14位的员工编号String account = "20191218000001";//往员工表里插入该用户的用户信息userServiceDao.saveUserInfo(username, account);//往人资表里插入该用户的工资信息try {salaryService.addSalaryInfo(account, salary);System.err.println(111);} catch (Exception e) {e.printStackTrace();}int i = 1 / 0;}
  • SalaryServiceImpl中的方法
@Transactional(propagation = Propagation.XXXX, rollbackFor = Exception.class)
@Override
public void addSalaryInfo(String account, BigDecimal salary) {salaryDao.addSalaryInfo(account, salary);//int i = 1 / 0;
}

如果addSalaryInfo方法标注的是PROPAGATION_NESTED时

  • 父级方法会发生回滚 —>user表里无法插入数据
  • 子级方法也会发生回滚 —>salary表里无法插入数据

如果addSalaryInfo方法标注的是REQUIRES_NEW时

  • 父级方法会发生回滚 —>user表里无法插入数据
  • 子级方法不会发生回滚 —>salary表里会插入数据

http://www.ngui.cc/el/1113709.html

相关文章

【spring事务源码学习】--- spring事务三大接口简介

文章目录1 前言2 TransactionDefinition接口3 PlatformTransactionManager接口4 TransactionStatus接口1 前言 spring为管理事务定义了三个接口,分别为 TransactionDefinition — 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则&#xff0…

【spring事务源码学习】--- spring事务核心组件创建过程

文章目录1 通过注解方式配置数据源事务管理器持久层框架2 spring事务核心组件的注册2.1 EnableTransactionManagement注解2.2 TransactionManagementConfigurationSelector类2.3 ProxyTransactionManagementConfiguration --- 三大核心组件2.4 AutoProxyRegistrar --- 事务核心…

【bean的生命周期】--- InstantiationAwareBeanPostProcessor接口简介

文章目录1 InstantiationAwareBeanPostProcessor接口简介2 bean的生命周期总结1 InstantiationAwareBeanPostProcessor接口简介 上篇文章写到spring-aop和spring事务核心后置处理器的前置处理方法入口都为下面的方法: 所在类: AbstractAutowireCapableB…

【spring源码】--- spring-aop和spring事务前置处理方法

文章目录1 简介2 前置处理方法的入口3 AOP的前置处理方法3.1 源码追踪3.1.1 applyBeanPostProcessorsBeforeInstantiation3.1.2 postProcessBeforeInstantiation3.1.3 AOP的shouldSkip方法 --- AOP切面通知解析的入口3.1.4 findCandidateAdvisors3.1.5 buildAspectJAdvisors --…

【spring事务源码学习】--- 目标对象增强核心源码解读

文章目录1 简单回顾2 如何找到适用于当前对象的通知---源码追踪2.1 findAdvisorsThatCanApply --- 入口2.2 AopUtils.findAdvisorsThatCanApply2.3 canApply --- 拿到当前类和当前类的接口,遍历接口和类中的方法看是否有适用于当前bean的通知2.4 matches2.5 getTran…

【spring事务源码学习】--- 目标方法调用流程核心源码解读

文章目录1 简述 源码跟踪入口2 目标方法调用流程核心源码解读2.1 invoke(...) --- 目标方法调用 调用结果返回流程的骨架2.2 proceed方法 --- 责任链递归调用模式的精髓2.3 invoke(this) 方法--- 以事务方式调用目标方法的入口2.4 invokeWithinTransaction --- 事务方式调用目…

【spring事务】 --- exposeProxy属性的作用 --- 同一个对象里方法间调用事务传播行为生效的方法

文章目录1 先看现象2 从源码看一下exposeProxy在事务源码中的逻辑3 解决方式源码地址:https://github.com/nieandsun/spring-study 1 先看现象 有如下代码,调用addUserAndSalary方法,t_user表和t_salary表哪个表里会被插入数据呢?&#xff1…

【bean的生命周期】--- BeanDefinition和BeanFactoryPostProcessor简介

文章目录1 单例业务bean的创建流程简介2 BeanFactoryPostProcessor修改BeanDefinition来干预bean的创建2.1 测试类2.2 BeanDefinition的class属性2.2 BeanDefinition的autowireMode属性2.3 BeanDefinition的constructorArgumentValues属性2.3.1 constructorArgumentValues中的a…

【Mybatis源码探索】 --- 开篇 • 搭建一个最简单的Mybatis框架

文章目录1 pom.xml2 主配置文件3 domain、mapper和mapper.xml4 测试启动类5 代码结构6 测试源码地址:https://github.com/nieandsun/mybatis-study 感觉比较简单,有不懂或有兴趣的可以clone下来代码看一下,一看肯定就都懂了。不过多解释了&am…

【Mybatis源码探索】 --- Mybatis配置文件解析核心源码解读

文章目录1 源码阅读入口2 配置文件解析核心源码解读2.1 SqlSessionFactoryBuilder --- 大骨架2.2 XMLConfigBuilder 和 parser.parse() --- 模板模式2.2.1 XMLConfigBuilder构造函数及BaseBuild的引出2.2.2 parser.parse()方法 --- mybatis-config.xml配置文件解析模版2.3 配置…