springboot中使用@Transactional注解事物不生效的坑
作者:张Sir66666 发布时间:2021-10-03 10:01:47
一:在springboot中使用事物遇到的坑
1.我们知道spring中的事物分为两种:一种是编程式事物,一种是声明式事物。顾名思义,编程式事物是指通过代码去实现事物管理,这里不做过多说明。另一种是声明式事物,分为两种情况01:一种是通过传统xml方式配置,02:使用@Transaction注解方式配置,这是主要讲解的是通过注解方式配置。因为在springboot项目中,会自动配置DataSourceTransactionManager,我们只需要在对应的方法上或者类上加上@Transaction就会自动接入到spring的事物中,让spring管理。
2.继续踩坑
**01坑:**如下图所示,我这边本地调用接口修改数据库张三口袋里面的金额,并且启用了事物管理,抛出RuntimeExecption。这时我们调用接口,我们可以看到事物生效了,数据库里面值并没有发生改变。但是,当我们把抛出的异常改为
throw new SQLTimeoutException(); 调用接口的时候,发现数据库张三的金额被改变了,事物没起作用,明明开启了事物,但是没起作用,这是为什么呢?
02坑: 在我们需要执行事物的方法,如果对异常进行抛出,并且我们手动捕获了这个异常的话,这时候事物也不会起作用的。如下图所示:
03坑:@Transaction注解只对方法名为pubic的才生效,其他事物不会生效。
04坑: 默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。
3.解决方案
01:Spring的事务管理默认是针对Error异常和RuntimeException异常以及其子类进行事务回滚。对runtimeException并不需要抛出,error需要抛出异常,并进行捕获。所以我们上面用到的SQLTimeoutException()并不属于这两者之间,我们需要手动回滚异常,在@Transaction注解里面指定回滚异常类型即可,我这里举一个例子@Transactional(rollbackFor = Exception.class)
02: 我们在需要执行的sercvice里面不应该主动捕获异常,这会导致我们事物不生效,应该继续往上抛,在controller层捕获即可,这样事物也生效了,异常也捕获了。
03:@Transaction注解只对方法名为pubic的才生效,其他事物不会生效。顾名思义,也就是说使用了@Transaction注解的,只能是public。因为只有@Transaction注解只有被其他方法调用才生效的,能被其他方法调用的方法,只能是public。
04:我们在使用事物注解的时候,尽量不要在类上面使用,这会使得类里面的所有方法都会有事物进行处理。比如说,我们一些方法只做查询操作,我们就没有必要再进行事物,我们应该在需要事物处理的方法上面加事物,并且指定回滚的异常类型。
二:既然说到spring的事物了,再说一下spring事物的隔离级别吧
原文 参考文章:https://www.jb51.net/article/204803.htm
Isolation :隔离级别
隔离级别是指若干个并发的事务之间的隔离程度,与我们开发时候主要相关的场景包括:脏读取、重复读、幻读。
我们可以看 org.springframework.transaction.annotation.Isolation 枚举类中定义了五个表示隔离级别的值:
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
}
DEFAULT :这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是: READ_COMMITTED 。
READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
REPEATABLE_READ :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
指定方法:通过使用 isolation 属性设置,例如:@Transactional(isolation = Isolation.DEFAULT)
Propagation:传播行为
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。
我们可以看 org.springframework.transaction.annotation.Propagation 枚举类中定义了6个表示传播行为的枚举值:
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
}
REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED 。
指定方法:通过使用 propagation 属性设置,例如:@Transactional(propagation = Propagation.REQUIRED)
来源:https://blog.csdn.net/Z__Sheng/article/details/89489053


猜你喜欢
- 本文实例讲述了java实现统计字符串中字符及子字符串个数的方法。分享给大家供大家参考,具体如下:这里用java实现统计字符串中的字符(包括数
- 前言:如果简单地拍照片并非您应用的主要目标,那么您可能希望从相机应用中获取图片并对该图片执行一些操作。一、这就是第一种方法,比较简单,不用将
- 什么是事务处理事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性 ( Consistency
- 前置工作:项目配置升到对应的29版本compileSdkVersion: 29,buildToolsVersion: ‘29.0.0'
- 案例说明:使用Java实现简单的斗地主洗牌发牌的操作;具体规则:共有54张牌,顺序打乱;三个玩家参与游戏,三人交替摸牌,每人17张牌,最后留
- 以下内容给大家介绍Android数据存储提供了五种方式:1、SharedPreferences2、文件存储3、SQLite数据库4、Cont
- 前言先说结论,tauri是一个非常优秀的前端桌面开发框架,但是,rust门槛太高了。一开始我是用electron来开发的,但是打包后发现软件
- 引入:前段时间去银行办业务,排队的人那是真多,自己正式办理业务也就不到5分钟,但是却足足等了两个小时(相信很多人都遇到过这种情况),对这种服
- springboot对压缩请求的处理最近对接银联需求,为了节省带宽,需要对报文进行压缩处理。但是使用springboot自带的压缩设置不起作
- 通常的函数调用 一个通常的函数调用的例子://自行包含头文件void MyFun(int x); //此
- 引言在第一篇文章中我们分析了协程启动创建过程启动过程,在本文中,我们将着重剖析协程中协程调度的逻辑流程。主要是分析解答如下2个问题:涉及到协
- 一、百度百科Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防
- 1.新建一个数组,把原来数组的内容搬到新数组中。这种方法实现的思路是:先新建一个数组(前提条件是长度得比原来的长),然后把原来数组的内容搬到
- 本文实例讲述了Android中CountDownTimer倒计时器用法。分享给大家供大家参考,具体如下:在平时我们编程的时候,经常会用到倒计
- 现在很多流行的框架,都可以很快的把分页效果做出来,但是作为一名程序员你必须得知道手写分页的流程:场景效果:一、分页的思路首先我们得知道写分页
- 本篇要点简单描述浮点数十进制转二进制精度丢失的原因。介绍几种创建BigDecimal方式的区别。整理了高精度计算的工具类。学习了阿里巴巴Ja
- 一、项目背景在实际工作中,会遇到业务比较集中的情况,随着时间推延,这部分业务关联的mysql表就会越来越大,十分臃肿。尽管在项目架构上做了读
- Windows 服务(即,以前的 NT 服务)使您能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计
- 发现问题最近在进行压测发现,有一些接口时好时坏,通过sentry日志平台及sky walking平台跟踪发现,用户张三获取到的用户上下文确是
- Mybatis插入对象时空值Mybatis中经常会有插入数据的情景,有时传输的对象字段并不是完整的,如果不做任何处理则会抛出异常,影响程序执