Java Spring声明式事务失效情况解决办法(天翼通讯)

 更新时间:2025年10月27日 08:49:00   作者:风浪很小  
在Spring的声明式事务中,多线程环境下事务会失效,因为子线程无法继承父线程的事务上下文,这篇文章主要介绍了Java Spring声明式事务失效情况解决办法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

事务失效排查清单

当事务不生效时,检查这个清单:

  • ✅ 方法是否是public?

  • ✅ 异常是否被正确抛出?

  • ✅ 是否配置了正确的rollbackFor?

  • ✅ 是否是内部调用?

  • ✅ 传播行为设置是否正确?

  • ✅ 是否配置了事务管理器?

  • ✅ 数据源是否支持事务?

Spring事务默认只回滚RuntimeExceptionError

想象Spring事务管理就像一个马戏团导演@Transactional注解就是他的指挥棒。但有时候,演员们不按导演的指挥来表演!

失效场景1:内部方法调用 - "导演被架空"

@Service
public class CircusService {
    
    public void bigShow() {
        System.out.println("开始大表演...");
        
        // 问题:在同一个类内部调用事务方法
        fireDance();  // 事务失效!
        
        // 相当于:导演喊"开始",但演员自己演自己的
    }
    
    @Transactional
    public void fireDance() {
        System.out.println("火焰舞蹈开始...");
        // 数据库操作...
        if (Math.random() > 0.5) {
            throw new RuntimeException("火焰太大!");
        }
        // 即使抛异常,事务也不会回滚!
    }
}

为什么会失效?

  • Spring事务基于AOP代理

  • 内部调用绕过了代理对象

  • 就像导演在外面喊,但演员在帐篷里听不见

失效场景2:异常类型不对 - "导演认错信号"

@Service
public class CircusService {
    
    @Transactional
    public void tightropeWalking() throws Exception {
        System.out.println("走钢丝表演...");
        // 数据库操作...
        
        // 问题:抛出了检查异常,但Spring默认只回滚运行时异常
        if (balanceTooLow()) {
            throw new Exception("平衡感不好!");  // 事务不回滚!
        }
        
        // 只有RuntimeException才会触发回滚
        throw new RuntimeException("摔下来了!");  // 这个会回滚
    }
}

失效场景3:异常被吃掉 - "导演没看到事故"

@Service
public class CircusService {
    
    @Transactional
    public void lionTaming() {
        try {
            System.out.println("驯狮表演...");
            // 数据库操作...
            throw new RuntimeException("狮子发怒了!");
        } catch (Exception e) {
            System.out.println("悄悄处理异常,导演没看见...");
            // 异常被捕获,事务不知道要回滚!
        }
    }
}

失效场景4:非public方法 - "导演管不了后台"

@Service
public class CircusService {
    
    @Transactional
    private void backstagePreparation() {  // 私有方法!
        System.out.println("后台准备工作...");
        // 事务失效!Spring代理无法拦截私有方法
    }
    
    @Transactional
    protected void equipmentCheck() {  // protected方法!
        // 同样可能失效,取决于代理方式
    }
}

失效场景5:错误的传播机制 - "导演指挥混乱"

@Service
public class CircusService {
    
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void clownPerformance() {
        System.out.println("小丑表演...");
        // 这个方法根本不在事务中运行!
        acrobatics();  // 即使调用的事务方法,也不会加入事务
    }
    
    @Transactional
    public void acrobatics() {
        // 因为外层没有事务,这里会开启新事务
    }
}

失效场景6:多数据源配置问题 - "多个导演抢指挥"

@Service
public class CircusService {
    
    // 如果配置了多个事务管理器,需要指定用哪个
    @Transactional  // 不指定的话,Spring不知道用哪个TransactionManager
    public void multiRingShow() {
        // 操作多个数据源...
    }
}

解决方案:

@Transactional("firstTransactionManager")  // 明确指定事务管理器
public void mainRingShow() {
    // 使用第一个数据源的事务
}
​
@Transactional("secondTransactionManager")  
public void secondRingShow() {
    // 使用第二个数据源的事务
}

总结

  • 内部调用 = 导演在外面喊,演员在帐篷里听不见

  • 异常类型不对 = 导演只认RuntimeException这种"紧急信号

  • 异常被吃掉 = 事故发生了,但没人告诉导演

  • 非public方法 = 导演管不了后台私事

  • 错误传播机制 = 导演指挥混乱

  • 多数据源配置问题 = 多个导演抢指挥

记住:Spring事务就像马戏团导演,必须让他在正确的时间、正确的地点、看到正确的事情,才能有效管理整个表演!

到此这篇关于Java Spring声明式事务失效情况解决办法的文章就介绍到这了,更多相关Java Spring声明式事务失效内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈java中Math.random()与java.util.random()的区别

    浅谈java中Math.random()与java.util.random()的区别

    下面小编就为大家带来一篇浅谈java中Math.random()与java.util.random()的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • spring boot系列之集成测试(推荐)

    spring boot系列之集成测试(推荐)

    这篇文章主要介绍了spring boot系列集成测试,需要的朋友可以参考下
    2018-03-03
  • java实现两张图片2D翻转动画效果

    java实现两张图片2D翻转动画效果

    这篇文章主要为大家详细介绍了java实现两张图片2D翻转动画效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Java 线程的生命周期完整实例分析

    Java 线程的生命周期完整实例分析

    这篇文章主要介绍了Java 线程的生命周期,结合完整实例形式分析了java线程周期相关的加锁、释放锁、阻塞、同步等原理与操作技巧,需要的朋友可以参考下
    2019-10-10
  • java UDP实现一个聊天工具的示例代码

    java UDP实现一个聊天工具的示例代码

    这篇文章主要介绍了java UDP实现一个聊天工具的示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • SpringBoot+Vue+Flowable模拟实现请假审批流程

    SpringBoot+Vue+Flowable模拟实现请假审批流程

    这篇文章主要为大家详细介绍了如何利用SpringBoot+Vue+Flowable模拟实现一个请假审批流程,文中的示例代码讲解详细,需要的可以参考一下
    2022-08-08
  • Mybatis-plus更新字段为null两种常用方法及优化

    Mybatis-plus更新字段为null两种常用方法及优化

    Mybatis Plus在进行更新操作时,默认情况下是不能将字段更新为null的,如果要更新字段为null,需要进行以下处理,这篇文章主要给大家介绍了关于Mybatis-plus更新字段为null的两种常用方法及优化,需要的朋友可以参考下
    2024-03-03
  • Spring配置多个数据源并实现动态切换示例

    Spring配置多个数据源并实现动态切换示例

    本篇文章主要介绍了Spring配置多个数据源并实现动态切换示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • 使用eclipse快速新建spirngboot项目的方法

    使用eclipse快速新建spirngboot项目的方法

    本篇文章主要介绍了使用eclipse快速新建spirngboot项目的方法,具有一定的参考价值,有兴趣的可以了解一下
    2017-04-04
  • spring boot 监听容器启动代码实例

    spring boot 监听容器启动代码实例

    这篇文章主要介绍了spring boot 监听容器启动代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10

最新评论