Spring事务传播中嵌套调用实现方法详细介绍
作者:宏远十一冠王 发布时间:2021-08-31 22:34:24
前言
最近在使用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类中,如果一个非事务方法调用一个带事务的方法和事务方法之间的相互调用都不会开启新的事务。
来源:https://blog.csdn.net/zly03/article/details/126330563
猜你喜欢
- springboot获取项目目录路径springboot部署后获取项目的路径//获取跟目录(绝对路径)File path = new Fil
- 1、Spring的事务管理主要包括3个接口TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的传
- Spring中BeanFactory FactoryBean和ObjectFactory的三种的区别引言关于FactoryBean 和 Be
- Java注解是在JDK5时引入的新特性,鉴于目前大部分框架(如spring)都使用了注解简化代码并提高编码的效率,因此掌握并深入理解注解对于
- 在看别人的关于CopyOnWriteArrayList 这个类的时候,看到有人提出了关于:数组拷贝的方法Arrays.copyOf() 的问
- 一:需求详情:OpenOffice.org 是一套跨平台的办公室软件套件,能在 Windows、Linux、MacOS X (X11)、和
- 前言公司最近在开发中遇到一个问题,在弄帖子的发布与回复问题,然后再iOS端和Android端添加表情的时候都会出错Caused by: ja
- 好久没有做web了,JSON目前比较流行,闲得没事,所以动手试试将对象序列化为JSON字符(尽管DotNet Framework
- /** * 三角数字: * 比达哥斯拉领导下的古希腊数学家发现了一个有趣的数字序列1, 3, 6, 10, 15, 21,... *
- 背景为了了解Seata AT模式的原理,我通过源码解读的方式画出了Seata AT模式启动的图示:如果是基于Springboot项目的话,项
- 1.多数据源配置类整体项目结构1).pom.xml 项目依赖<?xml version="1.0" encodin
- 本文研究的主要是优化MyBatis配置文件中的配置的相关内容,具体介绍如下。一、连接数据库的配置单独放在一个properties文件中之前,
- webservice的POST和GET请求调用POST请求1.发送请求import java.io.DataOutputStream;imp
- 目录Profile用法resourcesfilters多环境配置解决方案Profile用法我们在application.yml中为jdbc.
- (1). 和反射+泛型有关的接口类型java.lang.reflect.Type:java语言中所有类型的公共父接口java.lang.re
- 一、引言大家都知道单例模式,通过一个全局变量来避免重复创建对象而产生的消耗,若系统存在大量的相似对象时,又该如何处理?参照单例模式,可通过对
- java中的JsonSerializer用法背景今天在写项目的时候遇到一个问题,项目中有个类中有创建时间和更新时间两个属性,但是单位在后端用
- 本文实例讲述了eclipse中自动生成javadoc文档的方法。分享给大家供大家参考。具体方法如下:使用eclipse生成文档(javado
- 对于使用文件进行交换数据的应用来说,使用FTP 服务器是一个很不错的解决方案。关于FileZilla Server服务器的详细搭建配置过程,
- 一:JDBCTemplate简介Spring为各种持久化技术提供了简单操作的模板和回调API:ORM持久化技术模板类原生JDBCorg.sp