Spring事务@Transactional 注解下,事务失效的七种场景

Spring事务@Transactional 注解下,事务失效的七种场景

  1. 异常被捕获后没有抛出
    当异常被捕获后,并且没有再抛出,那么deleteUserA是不会回滚的。
@Transactional
public void deleteUser() {
    userMapper.deleteUserA();
    try {
        int i = 1 / 0;
        userMapper.deleteUserB();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  1. 抛出非运行时异常
    异步虽然抛出了,但是抛出的是非RuntimeException类型的异常,依旧不会生效。如果指定了回滚异常类型为Exception,那么就可以回滚非RuntimeException类型异常了。
    @Transactional(rollbackFor = Exception.class)
@Transactional
public void deleteUser() throws MyException{
    userMapper.deleteUserA();
    try {
        int i = 1 / 0;
        userMapper.deleteUserB();
    } catch (Exception e) {
        throw new MyException();
    }
}
  1. 方法内部直接调用
    如果先调用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();
 }
}
  1. 新开启一个线程
    如下的方式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();    
}
  1. 注解到private方法上
    private修饰的方式,spring无法生成动态代理
@Transactional
private void deleteUser() throws MyException{
    userMapper.deleteUserA();
    int i = 1/0;
    userMapper.deleteUserB();
}
  1. 数据库本身不支持
    mysql数据库,必须设置数据库引擎为InnoDB。
  2. 事务传播属性设置错误
    注意传播属性的设置,比如设置了:PROPAGATION_NOT_SUPPORIED(以非事务的方式执行,如果当前有事务则把当前事务挂起
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值