springboot中事务失效的一些场景以及如何应对
@Transactional是基于AOP的,因此事务发生需要两个条件:
1.添加@Transactional注解
2.使用代理对象
失效场景:同一个类中直接调用的类方法,而被调方法带有@Transactional
下面这段代码会抛出runtimeException异常,但是事务不会回滚。即insert生效了
因为b()在调用a()方法时,对象已经不再是代理对象,而是普通对象。而aop都是基于代理对象实现的,即aop是不关心普通对象头顶上注解的,因此事务会失效
@Transactional
public void a(){
int insert = mapper.insert(Entity);
if(insert<=0)
throw new RuntimeException("插入信息失败!");
}
public void b(){
a();
}
如果我们将代码块修改为下面这样,那么他是可以正常回滚的。此时其实只是发生了b()的回滚,因为a()抛出了异常给b()。如果这样写,其实a()的注解是无效的。达不到预期缩减事务代码块的目的
@Transactional
public void a(){
int insert = mapper.insert(Entity);
if(insert<=0)
throw new RuntimeException("插入信息失败!");
}
@Transactional
public void b(){
a();
}
解决办法:
那么如何让a()方法事务能够回滚呢?触发的两个条件,我们已经具备了第一个添加@Transactional注解,但是目前是普通的对象,而非代理对象。因此我们需要让a()由代理对象来实现
下例中,我们将a()方法写入service接口,然后通过注册一个本方法的bean,实现了代理对象,满足上述条件,可以对a()单独实现回滚
@Autowired
Service service;
@Transactional
public void a(){
int insert = mapper.insert(Entity);
if(insert<=0)
throw new RuntimeException("插入信息失败!");
}
public void b(){
service.a();
}
除此以外,还有一些其他让事务不能回滚的原因:
1.a()方法是private或者final的
我们知道,aop的实现是基于代理对象的。上述解决办法中,如果我们没有区分出impl。
那么一旦a方法私有化或者不可变的,会导致代理对象作为普通对象的子类,没有权限去通过AOP重写方法,会导致爆出空指针异常
2.数据库不支持事务、没有bean化的类:神仙难救
3.如果没有捕获到runtime或者error,spring是不会触发回滚的。
关于这点阿里规范中要求在@Transactional中指定rollbackFor,合理使用一般不会出现这个问题
还有如果仅仅是捕获了异常而没有抛出,那么也是不会触发回滚的
springboot中事务失效的一些场景以及如何应对的更多相关文章
- SpringBoot中常见的各种初始化场景分析
大家能区分出以下各种初始化适用的场景吗 ApplicationRunner,CommandLineRunner,BeanFactoryPostProcessor,InitializingBean,Be ...
- 就这?Spring 事务失效场景及解决方案
小明:靓仔,我最近遇到了很邪门的事. 靓仔:哦?说来听听. 小明:上次看了你的文章<就这?一篇文章让你读懂 Spring 事务>,对事务有了详细的了解,但是在项目中还是遇到了问题,明明加了 ...
- 聊聊spring事务失效的12种场景,太坑了
前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...
- @Transactional注解事务失效的几种场景及原因
1. 介紹 在业务开发的许多场景中,我们会使用到通过事务去控制多个操作的一致性.比较多的就是通过声明式事务,即使用 @Transactional 注解修饰方法的形式.但在使用过程中,要足够了解事务失效 ...
- SpringBoot 注解事务声明式事务
转载请注明: http://www.cnblogs.com/guozp/articles/7446477.html springboot 对新人来说可能上手比springmvc要快,但是对于各位从sp ...
- 面试突击83:什么情况会导致@Transactional事务失效?
一个程序中不可能没有事务,而 Spring 中,事务的实现方式分为两种:编程式事务和声明式事务,又因为编程式事务实现相对麻烦,而声明式事务实现极其简单,所以在日常项目中,我们都会使用声明式事务 @Tr ...
- SpringBoot设置事务管理
关于事务就不介绍了,前面在研究spring的时候就已经研究过了,参考:https://www.cnblogs.com/qlqwjy/p/7296493.html 这里直接研究springboot中事务 ...
- Spring事务Transactional和动态代理(三)-事务失效的场景
系列文章索引: Spring事务Transactional和动态代理(一)-JDK代理实现 Spring事务Transactional和动态代理(二)-cglib动态代理 Spring事务Transa ...
- 在springBoot与quartz 整合中 @Transaction 失效
问题1::springBoot在与quartz 整合时,使用@Transaction 注解时事务失效 解决方案:创建一个类使用@component被spring管理 ,使用@Transaction标识 ...
- [SpringBoot]SpringBoot中使用redis事务
本文基于SpringBoot 2.X 事务在关系型数据库的开发中经常用到,其实非关系型数据库,比如redis也有对事务的支持,本文主要探讨在SpringBoot中如何使用redis事务. 事务的相关介 ...
随机推荐
- dhcp报错
报错详情 查看dhcpd.service状态 使用命令检查配置文件报错 dhcpd -t -cf /etc/dhcp/dhcpd.conf 修改配置文件 重启dhcpd服务 [root@servera ...
- Java BigInteger类和BigDecimal()类
BigInteger类 BigInteger 支持任意精度的整数,可以准确的表达任何大小的整数而不丢失精准度 BigInteger 位于 java.math包中 BigInteger()括号里必须是字 ...
- kettle从入门到精通 第六十四课 ETL之kettle kettle中执行SQL脚本步骤,使用需当心
1.群里有不定时会有同学反馈执行SQL脚本步骤使用有问题,那么咱们今天一起来学习下该步骤.trans中的执行SQL脚本有两方面功能,使用时需小心,不然很容易踩坑. 官方定义: 翻译: 您可以使用此步骤 ...
- Windows Server 2016 离线安装.NET Framework 3.5
Windows Server 2016 离线安装.NET Framework 3.5 1.双击Windows Server 2016的ISO,会自动挂载,比如F盘. 2.右键开始菜单- 命令提示符(管 ...
- 已将此(这些)订阅标记为不活动,必须将其重新初始化。需要删除 NoSync 订阅,然后重
已将此(这些)订阅标记为不活动,必须将其重新初始化.需要删除 NoSync 订阅,然后重 查找状态不正常的发布 use distribution go select status,*from dbo. ...
- 安装nodejs易遇到的坑
@ 目录 背景描述 流程步骤 小结 背景描述 我的服务器是centos7.9,打算先直接通过yum安装,但是yum不能指定node版本,我直接指定显示404找不到,然后我设置了下node下载的源,还是 ...
- caddy 服务器的 Docker 镜像构建流程
构建一个包含 Caddy 服务器的 Docker 镜像,关键部分: https://github.com/caddyserver/caddy-docker/blob/master/Dockerfile ...
- 重学前端 - react-第二节: 添加ts + scss
重学前端 - react: 添加ts + scss 简介: 上一节我们新建了 react 项目.项目中并没有使用 ts + scss. 现在我们为项目添加 ts + scss.是项目后期维护更加方便, ...
- css 隐藏移动端滚动条
<template> <div id="app"> <router-view /> </div> </template htm ...
- rabbitMq消息没收到排查
rabbitMq消息没收到排查 首先看是否本地机器开了服务,或者测试环境里面其他的个人电脑本地服务启动注册了,都监听了同一个队列,导致队列消息被接走了.现象是在测试环境期望的执行没有运行.或者关注服务 ...