• spring事物失效场景及其解决方案


    一、错误的try catch导致事物不能回滚

    在catch中没有将异常抛出,因为事物通知只有捕捉到了目标抛出去的异常,才能进行后续的回滚处理,如果目标自己处理的异常,并没有抛出,事物通知是无法感知的。

    解决方案:

    方案一:异常原样抛出
    方案二:手动设置TransactionStatus.setRollbackOnly()
    在这里插入图片描述

    二、aop切面顺序导致事物不能正确回滚

    原因:事物切面优先级最低,但是日过自定义的切面的优先级和他一样,则还是自定义的切面在内层,这时若自定义的切面没用正确的抛出异常,事物则不能回滚
    解决方案:同上一个案例一样抛出异常即可。

    三、非public方法导致事物失效

    原因:spring为方法创建代理,添加0事物通知,前提都是该方法时public修饰的
    解决:改为public方法

    四、父子容器导致事物失效

    原因:子容器扫描的范围过大,把未添加事物配置的service扫描出来
    解决1:各扫描各的
    解决2:不要用父子容器,所有的bean都放在同一个容器里面
    父子容器只有在使用springMvc的这种老项目你们才会出现,使用springboot的项目都是一个容易,不会出现父子容器事物失效的情况。

    五、调用本类方法导致事物传播行为失效

    原因:本类方法调用不经过代理,因此无法增加,事物就会失效

    解决1:依赖注入自己的(代理)来调用,最简单的解决方案

    在这里插入图片描述

    解决2:添加开始代理对象的注解@EnableAspectJAutoProxy(exposeProxy=true),然后再代码中获取代理对象调用本类的方法

    在这里插入图片描述
    在这里插入图片描述

    六、@Transactional没有保证原子行为(多线程并发争抢同一个资源的时候会出现问题)

    原因:事物的原子性仅涵盖insert,update,delete,select… for update 语句,select方法并不阻塞

    解决1:通过synchrinazed保证目标方法的原子性

    在这里插入图片描述

    业务逻辑,先查询后两次更新

    在这里插入图片描述

    解决2:使用select… for update 替换select (排他锁,在做查询的时候,如果当前线程执行修改的语句没有commit提交,则其他线程阻塞)

    在这里插入图片描述

  • 相关阅读:
    为什么要学MySQL数据库,它有什么用?
    Java开发实习面试总结(49分钟)
    第三章. 业务功能开发--用户登录安全退出
    Linux系统基本使用 与 程序部署 - JavaEE初阶 - 细节狂魔
    【无标题】
    goioc:一个使用 Go 写的简易的 ioc 框架
    【吴恩达笔记】机器学习基础
    Voip测试工具
    Fourier分析入门——第11章——Fourier变换
    Android热修复Sophix的使用
  • 原文地址:https://blog.csdn.net/u014496893/article/details/126257039