当前位置:网站首页>@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是数据库链接,只有拥有同一个数据库链接才能同时提交和回滚,在不同的数据库连接中,是不同的事务,自然无法同时提交和回滚了
边栏推荐
- 一台服务器最大并发 tcp 连接数多少?65535?
- The 29th day of force deduction (DP topic)
- In 2021, the global foam protection packaging revenue was about $5286.7 million, and it is expected to reach $6615 million in 2028
- 强化学习-学习笔记1 | 基础概念
- thrift go
- Sword finger offer 30 Stack containing min function
- Use of CMD command
- CesiumJS 2022^ 源码解读[7] - 3DTiles 的请求、加载处理流程解析
- Print linked list from end to end
- Deep search DFS + wide search BFS + traversal of trees and graphs + topological sequence (template article acwing)
猜你喜欢
2.4 conversion of different data types
不同业务场景该如何选择缓存的读写策略?
《ActBERT》百度&悉尼科技大学提出ActBERT,学习全局局部视频文本表示,在五个视频-文本任务中有效!...
44. Concurrent programming theory
In 2021, the global foam protection packaging revenue was about $5286.7 million, and it is expected to reach $6615 million in 2028
In 2021, the global revenue of syphilis rapid detection kits was about US $608.1 million, and it is expected to reach US $712.9 million in 2028
Interval product of zhinai sauce (prefix product + inverse element)
How to handle wechat circle of friends marketing activities and share production and release skills
Line segment tree blue book explanation + classic example acwing 1275 Maximum number
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%
随机推荐
The 29th day of force deduction (DP topic)
6006. Take out the minimum number of magic beans
Global and Chinese market of rubidium standard 2022-2028: Research Report on technology, participants, trends, market size and share
Based on laravel 5.5\5.6\5 X solution to the failure of installing laravel ide helper
jvm jni 及 pvm pybind11 大批量数据传输及优化
Global and Chinese markets of cast iron diaphragm valves 2022-2028: Research Report on technology, participants, trends, market size and share
2.1 use of variables
Node MySQL serialize cannot rollback transactions
Operate BOM objects (key)
1.5 learn to find mistakes first
An old programmer gave it to college students
Use nodejs+express+mongodb to complete the data persistence project (with modified source code)
Test changes in Devops mode -- learning and thinking
P5.js development - setting
Derivation of decision tree theory
Wargames study notes -- Leviathan
Ruby replaces gem Alibaba image
String and+
Cesiumjs 2022 ^ source code interpretation [7] - Analysis of the request and loading process of 3dfiles
Do you really know how old you are?