当前位置:网站首页>@Transactional注解失效的场景
@Transactional注解失效的场景
2022-07-03 20:34:00 【cristianoxm】
Transactional用于在项目中开启事务,然后如果使用不当,也可能会导致事务失效,看看以下场景
修饰非public方法、修饰private、final、static方法:
这3种情况都可以从spring的源码中找到原因
protected TransactionAttribute computeTransactionAttribute(Method method,
Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
此方法会检查目标方法的修饰符是否为 public,不是 public则不会获取@Transactional 的属性配置信息。而final、static方法无法被代理重写方法,也会导致事务失效。
注意:private,protected、private 修饰的方法上使用 @Transactional 注解,虽然事务无效,但不会有任何报错,这是我们很容犯错的一点。
- 手动抛出别的异常, rollbackFor 设置错误
默认情况下,spring只会回滚RuntimeException和Error,对于普通的Excetion(非运行时异常),他不会回滚。因为spring团队认为非运行时异常是属于业务上的,开发人员应该主动进行处理而不是抛出给框架处理。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。

@Transactional(rollbackFor = MyException.class)
//@Transactional//这样事务失效
public void withoutRollBackFor(User user) throws MyException {
user.setAge(423442);
userMapper.update(user,new LambdaUpdateWrapper<User>().eq(true, User::getName,user.getName()));
//普通的Excetion(非运行时异常),事务失效,除非明确指定@Transactional(rollbackFor = MyException.class)
throw new MyException();
}
- 同一个类中方法调用,导致@Transactional失效
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public Integer insert(User user){
return userMapper.insert(user);
}
public void test(User user) throws MyException {
//这里其实是this.updateStatus(user);而不是proxy对象去调用
//该方式即使最后抛出了异常,到由于调用的是本对象,所以updateStatus的事务是失效的,执行完age被修改为423442
updateStatus(user);
}
@Transactional(rollbackFor = MyException.class)
public void updateStatus(User user) throws MyException {
user.setAge(423442);
userMapper.update(user,new LambdaUpdateWrapper<User>().eq(true, User::getName,user.getName()));
throw new MyException();
}
}
- 异常被 catch“吃了”导致@Transactional失效
@Transactional(rollbackFor = MyException.class)
public void rollbackFailed(User user){
try {
user.setAge(423442);
userMapper.update(user,new LambdaUpdateWrapper<User>().eq(true, User::getName,user.getName()));
throw new MyException();
}
catch (MyException e){
//手动回滚事务,不然事务失效
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//System.out.println("事务失效");
}
}
- 数据库引擎不支持事务
这种情况出现的概率并不高,事务能否生效数据库引擎是否支持事务是关键。常用的MySQL数据库默认使用支持事务的innodb引擎。一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了。
- 多线程调用导致事务失效
- 背景介绍
最近有一个大数据量插入的操作入库的业务场景,需要先做一些其他修改操作,然后在执行插入操作,由于插入数据可能会很多,
用到多线程去拆分数据并行处理来提高响应时间,如果有一个线程执行失败,则全部回滚。在spring中可以使用@Transactional注解去控制事务,使出现异常时会进行回滚,
在多线程中,这个注解则不会生效,如果主线程需要先执行一些修改数据库的操作,当子线程在进行处理出现异常时,主线程修改的数据则不会回滚,导致数据错误。
- 简单示例演示多线程事务
@Transactional(rollbackFor = MyException.class)
public void failedRollBackUnderMultipleThreads(User user) throws MyException {
user.setAge(423442);
userMapper.update(user,new LambdaUpdateWrapper<User>().eq(true, User::getName,user.getName()));
new Thread(()->{
//该事务方法是在另一个线程中,获取到的数据库链接不一样,从而跟上面是不同的是事务,即使下面抛出异常回滚,该方法也不会回滚
roleService.test();
}).start();
throw new MyException();
}
- 从源码角度分析:
spring的事务是通过数据库链接实现的,当前线程中保存了一个map,key是数据源,value是数据库链接,只有拥有同一个数据库链接才能同时提交和回滚,在不同的数据库连接中,是不同的事务,自然无法同时提交和回滚了
边栏推荐
- Task of gradle learning
- 设计电商秒杀系统
- It is discussed that the success of Vit lies not in attention. Shiftvit uses the precision of swing transformer to outperform the speed of RESNET
- 2.4 conversion of different data types
- [effective Objective-C] - block and grand central distribution
- Introduction to golang garbage collection
- JVM JNI and PVM pybind11 mass data transmission and optimization
- 47. Process lock & process pool & Collaboration
- Global and Chinese markets of polyimide tubes for electronics 2022-2028: Research Report on technology, participants, trends, market size and share
- 【c】 Digital bomb
猜你喜欢

Gee calculated area

Derivation of decision tree theory

1.4 learn more about functions

How can the outside world get values when using nodejs to link MySQL

2022 low voltage electrician examination and low voltage electrician simulation examination question bank

强化学习-学习笔记1 | 基础概念

2.4 conversion of different data types

2022 high voltage electrician examination and high voltage electrician reexamination examination

It is discussed that the success of Vit lies not in attention. Shiftvit uses the precision of swing transformer to outperform the speed of RESNET

TLS environment construction and plaintext analysis
随机推荐
jvm jni 及 pvm pybind11 大批量数据传输及优化
Global and Chinese markets of lithium chloride 2022-2028: Research Report on technology, participants, trends, market size and share
How to read the source code [debug and observe the source code]
Global and Chinese market of micro positioning technology 2022-2028: Research Report on technology, participants, trends, market size and share
【愚公系列】2022年7月 Go教学课程 002-Go语言环境安装
Measurement fitting based on Halcon learning -- Practice [1]
Oak-d raspberry pie cloud project [with detailed code]
Gauss elimination solves linear equations (floating-point Gauss elimination template)
The global industrial design revenue in 2021 was about $44360 million, and it is expected to reach $62720 million in 2028. From 2022 to 2028, the CAGR was 5.5%
Parental delegation mechanism
Thread, thread stack, method stack, the difference of creating thread
[postgresql]postgresql custom function returns an instance of table type
Global and Chinese market of rubidium standard 2022-2028: Research Report on technology, participants, trends, market size and share
Basic number theory -- Chinese remainder theorem
强化學習-學習筆記1 | 基礎概念
《ActBERT》百度&悉尼科技大学提出ActBERT,学习全局局部视频文本表示,在五个视频-文本任务中有效!...
Global and Chinese market of liquid antifreeze 2022-2028: Research Report on technology, participants, trends, market size and share
2.4 conversion of different data types
Node MySQL serialize cannot rollback transactions
In 2021, the global revenue of thick film resistors was about $1537.3 million, and it is expected to reach $2118.7 million in 2028