事物回滚与异常抛出的坑

下面总结异常不抛出的几种情况:

一、事物回滚默认:运行时异常(RuntimeException)和程序错误(Error)
下面这段代码事务不会回滚:

@Service
public class ProductServiceImpl implements ProductService {

   @Resource
   private ProductDao productDao ;
   
   @Override
   @Transactional
   public void insertProduct(Product product) throws Exception {
       // 插入产品信息
       productDao .insertProduct(product);
       // 手动抛出异常
       throw new SQLException("数据库异常");
   }
}

以上代码数据库插入仍然成功,因为spring boot项目,只有RuntimeException和error时,事物才会回滚。而以上代码跑出的是SQLException,所以插入数据库仍然成功。如果要一切异常都进行回滚,则在类上加下面这句即可:

@Transactional(rollbackFor = Exception.class)

二、try… catch…代码块将异常捕获,使事务不回滚
下面代码是很好的例子:

@Service
public class cityServiceImpl implements cityService {

   @Resource
   private CityDao cityDao;

   @Override
   @Transactional(rollbackFor = Exception.class)
   public void insertCity(City city) {
       try {
           // 插入城市信息
          cityDao .insertCity(city);
           // 手动抛出异常
           throw new SQLException("数据库异常");
       } catch (Exception e) {
           // 异常处理逻辑
       }
   }
}

因为手动抛出的异常被catch捕获了,所以代码没有执行抛出异常的那句,事务不会回滚。要回滚的方法就是不写catch语句。

三、事务的优先级大于锁的优先级
请看下面这段代码:

@Service
public class CityServiceImpl implements CityService {

   @Resource
   private CityDao cityDao;

   @Override
   @Transactional(rollbackFor = Exception.class)
   public synchronized void insertCity(City city) {
       // 插入操作
       cityDao.insertCity(city);
   }
}

批量操作时,会发现有重复的数据,一般情况下,已经存在的数据会进行更新,而不会二次插入。原因就在于举个例子:
a和b两条数据完全一样,a进入了插入方法,插入成功后,释放了锁,此时事务还没有结束,b进来调用了插入方法,因为事务没有结束,事务优先级大于锁的优先级,所以会插入两条完全一样的数据。
解决方法:一 、去掉事务;二、在外部调用这个CityServiceImpl 时加锁

本文参考了
微信公众号:程序员私房菜

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值