springboot 事务 Transaction 异常 Transaction rolled back because it has been marked as rollback-only

博客围绕Spring Boot中出现的Transaction rolled back because it has been marked as rollback-only异常展开。正常回滚可在catch中重新抛异常,而作者需求是不回滚让程序继续运行,还给出了参考资料。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

@Transactional(rollbackFor = Exception.class)
public void methodA()  {
    methodB();
}

public void methodB(){
    try{
        // 某段数据库操作方法触发异常,这个很重要哦,不是数据库操作方法触发不了事务回滚机制
        // 具体不太清楚,猜测类似于内部事务出现异常
    }catch(){
        logger.info("异常出现了,但不抛出,内部消化了");
    }

}

最终会抛出异常 Transaction rolled back because it has been marked as rollback-only

并回滚。

但是重点来了,正常如果想正常回滚,又不想出现这个 rollback-only 异常提示,只需要在catch中重新抛出异常就可以了,问题是我不想回滚,还想让程序走下去。

解决方法:

//事务管理
    private DataSourceTransactionManager dataSourceTransactionManager = SpringUtils.getBean(DataSourceTransactionManager.class);
    private TransactionDefinition transactionDefinition = SpringUtils.getBean(TransactionDefinition.class);

public void methodB(){
    try{
        // 手动开启一个事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        //这句代码是重点,
        dataSourceTransactionManager.setGlobalRollbackOnParticipationFailure(false);
        // 某段数据库操作方法触发异常,这个很重要哦,不是数据库操作方法触发不了事务回滚机制
        // 具体不太清楚,猜测类似于内部事务出现异常
    }catch(){
        logger.info("异常出现了,但不抛出,内部消化了");
    }
    // 提交事务
    dataSourceTransactionManager.commit(transactionStatus);
    // 恢复配置
    dataSourceTransactionManager.setGlobalRollbackOnParticipationFailure(true);

}

参考资料:Spring-Boot 出现Transaction marked as rollback only异常_- JackCen的博客-优快云博客

<think>好的,我现在需要帮助用户解决关于“Transaction rolled back because it has been marked as rollback-only异常的问题。首先,我得回顾一下用户提供的引用资料,整理出可能的原因和解决方案。 根据引用[1],这个异常Spring事务的传播行为有关,特别是REQUIRED、REQUIRES_NEW和NESTED的区别。可能当内层事务回滚时,外层事务被标记为rollback-only,导致提交时整体回滚。引用[2]提到,当内层事务抛出异常并被捕获后,外层事务在提交时检测到需要回滚,从而抛出异常。这说明异常处理不当可能是原因之一。 引用[3]指出该异常常发生在多业务场景中使用try-catch,导致事务嵌套混乱。解决方法是使用NESTED传播模式,让内层事务作为外层事务的嵌套子事务,这样内层的回滚不会强制外层回滚。引用[4]则建议避免随意捕获异常,确保只有能处理的异常才捕获,否则应抛出RuntimeException。 接下来,我需要将这些信息组织成结构清晰的回答,分点说明原因和解决方案。要注意使用中文,正确应用LaTeX格式,比如事务传播行为的类型可能需要用行内公式,如`REQUIRED`。同时,生成的相关问题要符合用户需求,可能涉及事务传播行为、异常处理、具体应用场景等。 需要确保回答正确引用每个来源,比如在解释原因时引用[^1][^2],解决方案引用[^3][^4]。另外,用户可能对事务传播行为的具体差异感兴趣,所以相关问题可以包括不同传播类型的区别、如何选择合适的事务传播行为等。 最后,检查是否符合系统级指令,如行内数学表达式是否正确使用$...$,独立公式是否用$$...$$,避免任何格式错误。同时确保回答真实可靠,引用来源准确。</think>### Transaction rolled back because it has been marked as rollback-only异常解析 #### 异常原因 1. **事务传播行为冲突** 当内层事务(如使用`REQUIRED`传播行为)抛出异常并被标记为回滚时,外层事务会被标记为`rollback-only`。此时即使外层事务尝试提交,也会因该标记强制回滚,导致异常。 2. **不恰当的异常捕获** 若内层事务异常被`try-catch`捕获但未重新抛出`RuntimeException`,外层事务无法感知异常,继续提交时会触发回滚。 3. **事务嵌套层级混乱** 使用默认的`REQUIRED`传播行为时,内外层事务共享同一事务上下文。若内层事务回滚,外层事务无法独立提交,导致矛盾。 #### 解决方案 1. **调整事务传播行为** - 使用`NESTED`传播模式:允许内层事务作为嵌套子事务独立回滚,不影响外层事务- 使用`REQUIRES_NEW`传播模式:创建新事务,完全隔离内外层事务(需注意锁和性能问题)。 2. **规范异常处理** - 仅捕获可处理的异常,否则重新抛出`RuntimeException`或其子类。 - 示例代码: ```java try { innerTransaction(); } catch (BusinessException e) { // 明确可处理的异常 // 处理逻辑 } catch (Exception e) { throw new RuntimeException(e); // 强制触发回滚 } ``` 3. **事务范围最小化** 避免在包含多个业务操作的代码块上使用事务,改为对原子操作单独控制事务--- $$ \text{事务传播行为选择公式} = \begin{cases} \text{REQUIRED} & \text{默认共享事务} \\ \text{NESTED} & \text{嵌套子事务} \\ \text{REQUIRES\_NEW} & \text{独立事务} \end{cases} $$ ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值