@Transactional 注解下,事务失效的七种场景
1、异常被捕获后没有抛出
当异常被捕获后,并且没有再抛出,那么deleteUserA
是不会回滚的
@Transactional
public void deleteUser() {
userMapper.deleteUserA();
try {
int i = 1 / 0;
userMapper.deleteUserB();
} catch (Exception e) {
e.printStackTrace();
}
}
2、抛出非运行时异常
异步虽然抛出了,但是抛出的是非RuntimeException
类型的异常,依旧不会生效。
@Transactional
public void deleteUser() throws MyException{
userMapper.deleteUserA();
try {
int i = 1 / 0;
userMapper.deleteUserB();
} catch (Exception e) {
throw new MyException();
}
}
如果指定了回滚异常类型为Exception,那么就可以回滚非RuntimeException
类型异常了。
@Transactional(rollbackFor = Exception.class)
3、方法内部直接调用
如果先调用deleteUser()
,那么deleteUserA()
是不会回滚的,其原因就是@Transactional
根本没生成代理,如果直接调用deleteUser2()
那么没问题,deleteUserA()
会回滚。
public void deleteUser() throws MyException{
deleteUser2();
}
@Transactional
public void deleteUser2() throws MyException{
userMapper.deleteUserA();
int i = 1 / 0;
userMapper.deleteUserB();
}
修改方式,把当前类自己注入一下调用即可。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
//自己注入自己
@Autowired
UserService userService;
public void deleteUser() throws MyException{
userService.deleteUser2();
}
@Transactional
public void deleteUser2() throws MyException{
userMapper.deleteUserA();
int i = 1 / 0;
userMapper.deleteUserB();
}
}
4、新开启一个线程
如下的方式deleteUserA()
也不会回滚,因为spring实现事务的原理是通过ThreadLocal把数据库连接绑定到当前线程中,新开启一个线程获取到的连接就不是同一个了。
@Transactional
public void deleteUser() throws MyException{
userMapper.deleteUserA();
try {
//休眠1秒,保证deleteUserA先执行
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() -> {
int i = 1/0;
userMapper.deleteUserB();
}).start();
}
5、注解到private方法上
idea直接会给出提示Methods annotated with ‘@Transactional’ must be overridable
,原理很简单,private修饰的方式,spring无法生成动态代理。
@Transactional
private void deleteUser() throws MyException{
userMapper.deleteUserA();
int i = 1/0;
userMapper.deleteUserB();
}
6、数据库本身不支持
mysql数据库,必须设置数据库引擎为InnoDB。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2021-08-02 4种经典限流算法
2021-08-02 规范