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事务. 事务的相关介 ...
随机推荐
- Linux系统编程(十)线程池
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h& ...
- IPsecVPN 服务器一键安装脚本
IPsec VPN 服务器一键安装脚本 使用 Linux 脚本一键快速搭建自己的 IPsec VPN 服务器.支持 IPsec/L2TP, Cisco IPsec 和 IKEv2 协议.你只需提供自己 ...
- Swift全局变量的线程安全分析
一.示例代码 import UIKit let obj = TestObj() class TestObj { init() { print("\(type(of: self)) init& ...
- python的一些常用编码技巧(持续更新)
语法问题 我常用的库函数 1 copy库 import copy copy.deepcopy() 2.list库 from typing import List 获取迭代对象的第一个值 方法一:使用l ...
- SHA256/SHA512码计算方式
(1)Windows系统计算SHA256/SHA512码的方式: certutil -hashfile yourfilename SHA256/SHA512 以计算readme.txt文档进行说明: ...
- 【WPF】Dispatcher 与消息循环
这一期的话题有点深奥,不过按照老周一向的作风,尽量讲一些人鬼都能懂的知识. 咱们先来整个小活开开胃,这个小活其实老周在 N 年前写过水文的,常阅读老周水文的伙伴可能还记得.通常,咱们按照正常思路构建的 ...
- Java第二次Blog
7-4~6题目集 前言 这些题目主要用到对象与类的处理继承与多态的使用: 继承和多态是面向对象编程中相互关联的两个概念.继承为多态提供了基础,而多态则通过继承实现了代码的灵活性和可扩展性. 1.字符串 ...
- EF MYSQL 出现:输入字符串的格式不正确
实体类字段和数据库类型不一致. 比如:数据库是char类型字段,程序里声明为int.
- mongodb数据库连接格式
mongodb数据库连接格式 mongodb://账号:密码@mongodb服务器IP:27017/数据库名称
- 向web服务器下载文件
web服务器向客户端发送文件 Web服务器读取一个文件的二进制数据,把这组二进制数据发送个客户端,服务器发送给客户端的HTML文档的本质也是二进制.客户端使用以下代码读文件 response = ur ...