Spring事务传播中嵌套调用实现方法详细介绍

目录
  • 前言
  • 7种传播方式
  • 注解式事务
  • 事务的方法之间的调用
  • 注意事项

前言

最近在使用Spring框架时遇到了一些问题,主要是Spring的事务传播问题,一个不带事务的方法调用带事务的方法,有时候会出现不回滚的情况,所以写了这篇文章来记录一下。

7种传播方式

我们先来看Spring事务的7中传播方式以及对应的描述

属性名称 描述
PROPAGATION__REQUIRED REQUIRED 表示的是当前这个方法必须运行在一个事务环境中,如果当前方法已经处于事务环境中,就可以直接使用该方法,否则开启一个新的事务
PROPAGATION_SUPPORTS SUPPORTS 如果当前方法处于事务环境中,就使用当前事务,否则不使用事务
PROPAGATION_MANDATORY MANDATORY 表示当前方法一定要处于事务环境中,否则就抛出异常
PROPAGATION_REQUIRES_NEW REQUIRES_NEW 当前方法需要运行在新的事务中。如果当前方法已在事务环境中,先暂停当前事务,在启动新的事务方法后才执行该方法,如果当前方法不在事务环境中,就启动一个新的事务后启动执行该方法。
PROPAGATION_NOT_SUPPORTED NOT_SUPPORTED 不支持当前的事务,总是以非事务状态执行。如果这个方法是事务方法,就先挂起这个事务方法,再执行这个方法
PROPAGATION_NEVER NEVER 不支持当前事务,如果是事务方法,则抛出异常
PROPAGATION__NESTED NESTED 如果当前执行的方法处于事务环境中,依旧会启动一个事务,嵌套的事务也可以独立于当前事务独立回滚和提交,如果当前执行的方法不在事务环境中,也会启动一个新事务。

注解式事务

在Spring中,我们常用@Transactional来标注一个事务方法,如果有点进去这个注解的源码都可以看到Spring对于添加这个注解的方法,都会默认将这个方法的事务的传播等级设置为REQUIRED,也就是是当前方法必须处于一个事务方法中,或者使用调用这个方法的事务行为。

下面我们来分析下这个注解在什么情况下会失效,并且需要怎么样来去避免这种情况的发生。

事务的方法之间的调用

下面这个例子模仿的是一个带事务的方法调用另外一个事务方法,在下面的这个方法报错,查看当前事务有没有进行回滚

@Override
    @Transactional(rollbackFor = Exception.class)
    public void saveWithDish(SetmealDto setmealDto){
        this.save(setmealDto);
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveBa(List<SetmealDish> setmealDishes, SetmealDto setmealDto) throws Exception{
        setmealDishes = setmealDishes.stream().peek((item) -> item.setSetmealId(setmealDto.getId())).collect(Collectors.toList());
        setmealDishService.saveBatch(setmealDishes);
        int j = 2/0;
    }

根据事务的传播等级来看,这种情况是肯定可以回滚的,但是如果是同一类中,像下面这种情况,同一个类中一个不带事务的方法调用另外一个带事务的方法,这种情况下它的事务会不会回滚呢?理论上我们觉得是会的,但是在测试的时候呢,我们发现这个事务并没有进行回滚,也就是说,这个事务注解@Transantional没有生效

@Override
    public void saveWithDish(SetmealDto setmealDto) throws Exception{
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        saveBa(setmealDishes, setmealDto);
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveBa(List<SetmealDish> setmealDishes, SetmealDto setmealDto) throws Exception{
        this.save(setmealDto);
        setmealDishes = setmealDishes.stream().peek((item) -> item.setSetmealId(setmealDto.getId())).collect(Collectors.toList());
        setmealDishService.saveBatch(setmealDishes);
        int j = 2/0;
    }

虽然这里我们报错了,但是数据库中还是新增了一条刚刚我们添加的一条数据,这样可以说明,这是没有添加事务的,也验证了上面我们的方法。

下面我们来看情况上,当不同类之间类方法的调用,如果一个事务方法调用一个非事务方法,这样非事务方法当然可以获取到当前这个事务的,不会开启一个新的事务。但是当一个非事务方法调用一个不同类的事务方法时,这样会不会回滚呢,答案是会的,这边我已经进行验证过了。

注意事项

我们需要记住Spring的默认事务传播等级是Required,在Spring扫描Bean时,会扫描这个方法是否带有@Transactional注解,如果是包含的话,Spring会动态生成一个代理类(proxy),当这个方法被调用时,是由代理类来进行调用的,而在初始化时,同一个类下面,这个方法如果是没有带@Transactional注解调用一个@Transactional的方法的话,这个方法的调用是没有经过代理类的,就不会启动transactional,也就是在同一个类出现无效的现象出现

所以,解决的话,我们可以将这两个方法分开到两个不同的类中,所以我们可以知道在一个service类中,如果一个非事务方法调用一个带事务的方法和事务方法之间的相互调用都不会开启新的事务。

到此这篇关于Spring事务传播中嵌套调用实现方法详细介绍的文章就介绍到这了,更多相关Spring嵌套调用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入了解Spring的事务传播机制

    目录 Spring 事务传播机制有哪些? 事务传播机制使用与演示 REQUIRED 使用演示 REQUIRED_NEW 使用演示 NESTED 使用演示 总结 Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的. 既然是“事务传播”,所以事务的数量应该在两个或两个以上,Spring 事务传播机制的诞生是为了规定多个事务在传播过程中的行为的.比如方法 A 开启了事务,而在执行过程中又调用了开启事务的 B 方法,那么 B 方法的事务是应该加入到 A 事务当中

  • 浅谈Spring事务传播行为实战

    Spring框架提供了事务管理的标准实现,且可以通过注解或者XML文件的方式声明和配置事务. 通过异步事件的方式解耦服务调用,可以提高程序的响应速度,并且避免因为事务传播行为而导致的事务问题. 本文以一个电商平台包裹出库的业务为实际背景,通过异步事件与线程池的方式解耦嵌套事务,提高程序并发性能:为了便于问题的分析和方案的理解,同时还讲解了Spring的事务管理,并着重介绍了几种不同的事务传播行为. 事务小贴士 什么是事务呢?简单来讲事务就是逻辑上的一组操作,这些操作要么都执行,要么都不执行. 什

  • 关于spring事务传播行为非事务方式的理解

    目录 spring事务传播行为非事务方式 Spring事务理解和配置 1 Spring事务 1.1 事务简介 1.2 事务的传播行为 1.3 编程式事务(需要手动写代码,了解) 1.4 声明式事务(xml配置) 1.5 声明式事务(注解) spring事务传播行为非事务方式 具体的隔离级别可以看看搜一下,相关的博客挺多的,现在说一下对传播行为 PROPAGATION_NOT_SUPPORTED.PROPAGATION_NEVER中很多解释为 非事务方式运行 的理解.    关于什么是'非事务方式

  • Spring超详细讲解事务和事务传播机制

    目录 为什么需要事务 Spring 声明事务 Transactional参数说明 propagation isolation timeout 事务回滚失效解决方案 @Transactional工作原理 Spring 事务的传播机制 为什么需要事务传播机制? 传播机制的类型 为什么需要事务 事务是将一组操作封装成一个执行单元,要么全部成功,要么全部失败.如果没有事务,转账操作就会出现异常,因此需要保证原子性. Spring 声明事务 只需要在方法上添加@Transactional注解就可以实现,无

  • Spring中的事务传播行为示例详解

    一.背景介绍 Spring 框架应该是每一个人 javaer 都必须接触和学习的技术,Spring 公司所提供的各种框架是 Java 开发行业可参考的重要标准之一. Spring 中有 7 种类型的事务传播行为.事务传播行为是 Spring 框架提供的一种事务管理方式,它是 Spring 框架之中非常重要的一个技术点,毕竟事务关系到应用程序和数据库的交互,而数据更是互联网行业最为重要的资源. 平时开发过程中事务都会有使用,但是没有真正地总结过,尤其是事务中嵌套事务的场景,此篇基础知识文在此做一个

  • 老生常谈spring的事务传播机制

    目录 spring的事务传播机制 1.why 为什么会有事务传播机制? 2.传播机制生效的条件 解决方案 3.传播机制类型 PROPAGATION_REQUIRED (默认) REQUIRES_NEW (一般用在子方法需要单独事务) NESTED SUPPORTS NOT_SUPPORTED MANDATORY NEVER spring的事务传播机制 背景:实习期间几次遇到事务方法,有一次本地测试时发现事务没有回滚,就把简单描述写在wx上,今天来给spring事务做个自我总结. 1.why 为什

  • Spring事务传播行为问题解决

    这篇文章主要介绍了Spring事务传播行为问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.简介 Spring事务配置及相关说明详见:https://www.jb51.net/article/177710.htm.这里说明spring事务的几点注意: 1.默认只会检查回滚RuntimeException的异常. 2.@Transactional注解只能作用于public的方法上,默认传播行为 Propagation.REQUIRED

  • Spring源码解析之事务传播特性

    一.使用方式 可以采用Transactional,配置propagation即可. 打开org.springframework.transaction.annotation.Transactional可见默认传播特性是REQUIRED. /** * The transaction propagation type. * <p>Defaults to {@link Propagation#REQUIRED}. * @see org.springframework.transaction.inte

  • Spring事务传播中嵌套调用实现方法详细介绍

    目录 前言 7种传播方式 注解式事务 事务的方法之间的调用 注意事项 前言 最近在使用Spring框架时遇到了一些问题,主要是Spring的事务传播问题,一个不带事务的方法调用带事务的方法,有时候会出现不回滚的情况,所以写了这篇文章来记录一下. 7种传播方式 我们先来看Spring事务的7中传播方式以及对应的描述 属性名称 值 描述 PROPAGATION__REQUIRED REQUIRED 表示的是当前这个方法必须运行在一个事务环境中,如果当前方法已经处于事务环境中,就可以直接使用该方法,否

  • Android中imageview.ScaleType使用方法详细介绍

    Android中imageview.ScaleType使用方法详细介绍 ScaleType属性用以表示显示图片的方式,共有8种取值: ScaleType.CENTER:图片大小为原始大小,如果图片大小大于ImageView控件,则截取图片中间部分,若小于,则直接将图片居中显示. ScaleType.CENTER_CROP:将图片等比例缩放,让图像的短边与ImageView的边长度相同,即不能留有空白,缩放后截取中间部分进行显示. ScaleType.CENTER_INSIDE:将图片大小大于Im

  • mysql中show指令使用方法详细介绍

    本文主要介绍mysql数据库下show命令的主要用法 a. show tables或show tables from database_name; -- 显示当前数据库中所有表的名称. b. show databases; -- 显示mysql中所有数据库的名称. c. show columns from table_name from database_name; 或show columns from database_name.table_name; -- 显示表中列名称. d. show

  • Spring事务传播属性和隔离级别详细介绍

    1 事务的传播属性(Propagation) 1) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exists. 如果存在一个事务,则支持当前事务.如果没有事务则开启一个新的事务. 被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域.如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务. 2) MANDATORY Support a curren

  • Spring事务管理中关于数据库连接池详解

    目录 Spring事务管理 环境搭建 标准配置 声明式事务 总结 SqlSessionFactory XML中构建SqlSessionFactory 获得SqlSession的实例 代码实现 作用域(Scope)和生命周期 SqlSessionFactoryBuilder(构造器) SqlSessionFactory(工厂) SqlSession(会话) Spring事务管理 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序

  • java编程中实现调用js方法分析

    本文实例讲述了java编程中实现调用js方法.分享给大家供大家参考,具体如下: /* * 加载脚本引擎,并在java中调用js方法 */ public void test2() { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); try { String str="2&1"

  • JavaScript中如何调用Java方法

    在JavaScript中想要调用Java的方法,我通过JavaScript访问servlet,再通过servlet调用Java某个类的方法. HTML代码 <table id="cartTable"> <thead> <tr> <th class="product_remove"> <label> <input class="check-all check" type="

  • SpringCloud Gateway DispatcherHandler调用方法详细介绍

    目录 前言 DispatcherHandler类声明 handle方法 最后总结一下 前言 之前几节我们分析了请求是如何调用到HttpWebHandlerAdapter的,然后再调用到DispatcherHandler中,通过handle方法来处理具体的请求. DispatcherHandler的注入在自动装配那一节已经说过了,忘记的同学可以重新会看一下. DispatcherHandler类声明 public class DispatcherHandler implements WebHand

随机推荐