程序员

大厂数据库事务实践-事务生效就能保证正确回滚?

2020-11-18  本文已影响0人  JavaEdge

AOP实现事务:使用try?c/atch包裹@Transactional注解的方法,当方法出现异常并满足一定条件时,在catch里可设置事务回滚,没有异常则直接提交事务。

“一定条件”包括:

打开Spring的DefaultTransactionAttribute

反面教材

注册用户:

createUserError1、2这俩方法的实现和调用,虽然避开了事务不生效的坑,但因异常处理不当,文件操作出现异常时依旧不回滚事务。

修复bug

以及如何通过日志来验证是否修复成功。针对这2种情况,对应的修复方法如下。

1 如果希望自己捕获异常并处理,可手动设置让当前事务处回滚态

@Transactional
public void createUserRight1(String name) {
    try {
        userRepository.save(new UserEntity(name));
        throw new RuntimeException("error");
    } catch (Exception ex) {
        log.error("create user failed", ex);
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

查看日志,事务确定回滚。

Transactional code has requested rollback:手动请求回滚。

2 在注解中声明,期望遇到所有的Exception都回滚事务

以突破默认不回滚受检异常的限制。

image

查看日志,提示回滚:
[图片上传失败...(image-cd575d-1605664603758)]

该案例有DB操作、IO操作,在IO操作问题时期望DB事务也回滚,以确保逻辑一致性。

小结

由于异常处理不正确,导致虽然事务生效,但出现异常时没回滚。
Spring默认只对被@Transactional注解的方法出现RuntimeExceptionError时回滚,所以若方法捕获了异常,就需要通过手写代码处理事务回滚。
若希望Spring针对其他异常也可回滚,可相应配置@Transactional注解的rollbackFornoRollbackFor属性覆盖Spring的默认配置。

有些业务可能包含多次DB操作,不一定希望将两次操作作为一个事务,这时就需仔细考虑事务传播的配置。

上一篇 下一篇

猜你喜欢

热点阅读