You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用多Repository时MongoDB响应式事务不生效问题排查

问题原因及解决方案

核心问题分析

  1. subscribe()调用脱离事务上下文
    你直接调用firstRepository.save().subscribe()会立即触发数据库操作,完全脱离了@Transactional管理的反应式事务上下文。反应式事务依赖ReactiveTransactionContext在Mono/Flux的链式调用中传播,一旦手动调用subscribe(),操作会在独立线程执行,不受当前事务约束。

  2. 同步异常无法触发反应式事务回滚
    直接抛出RuntimeException这类同步异常,无法被反应式事务上下文感知。反应式方法的异常必须通过Mono.error()包装,事务管理器才能捕获异常并执行回滚逻辑。

  3. 操作未形成反应式链式调用
    两个保存操作没有通过Mono/Flux的链式方法(如flatMap)串联,导致第一个保存操作独立于事务边界之外,不受事务控制。

修正后的代码示例

ApiService修正版

@Service
@RequiredArgsConstructor
public class ApiService {

    private final FirstRepository firstRepository;
    private final SecondRepository secondRepository;

    @Transactional
    public Mono<SecondDocument> save(FirstDocument firstDocument, SecondDocument secondDocument) {
        return firstRepository.save(firstDocument)
                .flatMap(savedFirst -> {
                    // 模拟异常,用Mono.error抛出
                    return Mono.error(new RuntimeException("test"));
                    // 正常流程执行第二个保存
                    // return secondRepository.save(secondDocument);
                });
    }
}

关键修正点

  • 移除subscribe()调用,用flatMap串联操作,确保所有数据库操作处于同一事务上下文。
  • 用Mono.error()抛出异常,让反应式事务管理器捕获并触发回滚。
  • 所有操作通过反应式链式调用串联,保证事务覆盖完整操作流程。

额外注意事项

  • 确认MongoDB集群支持事务:你使用的Atlas 6.0.11版本满足要求,但需保证连接字符串中的副本集配置正确。
  • 配置类中@EnableTransactionManagement已正确开启,无需修改。
  • 调用该方法时需通过反应式方式订阅(如Controller返回Mono由Spring Web自动订阅),禁止在方法内部手动调用subscribe()。

内容的提问来源于stack exchange,提问作者zellcorp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 23:26:17