常见问题整理
1.当标记了@Transactional注解的方法中出现异常时,如果该异常未传播到该方法外,则事务不会回滚,反之,只有异常传播到该方法外,事务才会回滚
错误示例:
// 异常被try-catch了
@Override
@Transactional
public Result firstFunctionAboutException() {
try{
log.info("减库存开始");
goodsStockMapper.updateStock();
if(1 == 1) throw new RuntimeException();
return Result.ok();
}catch (Exception e){
log.info("减库存失败!" + e.getMessage());
return Result.server_error().Message("减库存失败!" + e.getMessage());
}
}
正确示例:
@Override
@Transactional
public void secondFunctionAboutException() {
log.info("减库存开始");
goodsStockMapper.updateStock();
if(1 == 1) throw new RuntimeException();
}
2.默认情况下,如果我们抛出的不是RuntimeException时,事务不会回滚,需要手动抛出RuntimeException异常或者修改@Transactional注解默认配置
错误示例
@Override
@Transactional
public void thirdFunctionAboutException() throws Exception {
log.info("减库存开始");
goodsStockMapper.updateStock();
if(1 == 1) throw new Exception();
}
正确示例
// 抛出RuntimeException
@Override
@Transactional
public void thirdFunctionAboutException1(){
try{
log.info("减库存开始");
goodsStockMapper.updateStock();
if(1 == 1) throw new Exception();
}catch (Exception e){
log.info("出现异常"+e.getMessage());
throw new RuntimeException("手动抛出RuntimeException");
}
}
// 指定回滚异常
@Override
@Transactional(rollbackFor = Exception.class)
public void thirdFunctionAboutException2() throws Exception {
log.info("减库存开始");
goodsStockMapper.updateStock();
if(1 == 1) throw new Exception();
}
3.被注解的方法必须是public的,且必须由注入bean来直接调用才能事务回滚
错误示例
//在普通方法中调用事务方法
@Override
public void privateFunctionCaller (){
privateCallee();
}
// 使用private修饰
@Transactional
private void privateCallee(){
goodsStockMapper.updateStock();
throw new RuntimeException();
}
正确示例
@Override
@Transactional
public void publicCallee(){
goodsStockMapper.updateStock();
throw new RuntimeException();
}
// 使用自身service调用,或者将两个方法放置于不同的service
@Autowired
private GoodsStockService self;
@Override
public void aopSelfCaller (){
self.publicCallee();
}