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实现Redis的集合(set)命令操作

    Java实现Redis的集合(set)命令操作

    这篇文章主要介绍了Java实现Redis的集合(set)命令操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • 详解java中String值为空字符串与null的判断方法

    详解java中String值为空字符串与null的判断方法

    这篇文章主要介绍了详解java中String值为空字符串与null的判断方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

    Java编程实现基于图的深度优先搜索和广度优先搜索完整代码

    这篇文章主要介绍了Java编程实现基于图的深度优先搜索和广度优先搜索完整代码,具有一定借鉴价值,需要的朋友可以了解下。
    2017-12-12
  • java实现emqx设备上下线监听详解

    java实现emqx设备上下线监听详解

    这篇文章主要为大家介绍了java实现emqx设备上下线监听详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • java中判断json key是否存在的几种方法

    java中判断json key是否存在的几种方法

    在使用Java处理JSON数据时,如何判断某一个key是否存在?本文就来介绍三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • java实现MD5加密方法汇总

    java实现MD5加密方法汇总

    本文给大家汇总介绍了2种java实现MD5加密的方法,非常的实用,这里分享给大家,学习下其中的思路,对大家学习java非常有帮助。
    2015-10-10
  • RabbitMQ实现消费端限流的步骤

    RabbitMQ实现消费端限流的步骤

    消费者端限流的主要目的是控制消费者每次从 RabbitMQ 中获取的消息数量,从而实现消息处理的流量控制,这篇文章主要介绍了RabbitMQ如何实现消费端限流,需要的朋友可以参考下
    2024-03-03
  • java后端进行跨域的几种方式小结

    java后端进行跨域的几种方式小结

    本文主要介绍了java后端进行跨域的几种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 带你快速搞定java数组

    带你快速搞定java数组

    数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们数组的声明创建
    2021-07-07
  • MyBatis-Plus 乐观锁的具体实现

    MyBatis-Plus 乐观锁的具体实现

    MyBatis-Plus 的乐观锁通过简单的配置和注解,可以轻松实现高并发场景下的数据并发控制,具有一定的参考价值,感兴趣的可以了解一下
    2024-09-09

最新评论