SpringBoot3默认不启用MongoDB事务,必须显式配置MongoTransactionManager并使用副本集URI、MongoDatabaseFactory及MongoTemplate。

SpringBoot3 默认不启用 MongoDB 事务,必须显式配置
SpringBoot3(基于 Spring 6+)对 MongoDB 事务的支持不再自动生效,即使你用了 spring-boot-starter-data-mongodb,@Transactional 注解对 Mongo 操作也完全无效——除非你手动注册 MongoTransactionManager。这是和 SpringBoot2 最关键的区别,很多项目升级后事务突然“不回滚”,根源就在这里。
必须用 MongoDatabaseFactory 替代已弃用的 MongoDbFactory
SpringBoot3 中 MongoDbFactory 已被移除,直接使用它会编译失败或启动报 NoClassDefFoundError。正确方式是注入 MongoDatabaseFactory 并传给 MongoTransactionManager 构造器:
@Configuration
public class MongoTransactionConfig {
@Bean
public MongoTransactionManager transactionManager(MongoDatabaseFactory factory) {
return new MongoTransactionManager(factory);
}
}
- 不要写
@ConditionalOnProperty包裹这个 Bean —— 它只应在副本集/分片集群环境启用,但判断逻辑应放在部署层(如 profile 或 config server),而非硬编码在 Bean 定义里 - 如果应用连接的是单节点 MongoDB(非副本集),启动时不会报错,但运行时调用
@Transactional方法会抛出MongoCommandException: Command failed with error 281 (NoSuchTransaction) -
MongoDatabaseFactory是 Spring Boot 3 自动配置好的 Bean,无需额外声明
application.yml 必须指向副本集 URI,且不能省略 replicaSet 参数
仅靠 mongodb://host:port/db 格式无法触发事务支持。MongoDB 驱动需要明确知道这是副本集,否则不会启用事务上下文。URI 必须包含 ?replicaSet= 查询参数:
spring:
data:
mongodb:
uri: mongodb://localhost:27017,localhost:27018,localhost:27019/mydb?replicaSet=rs0
- 三个节点地址用英文逗号分隔,不能有空格
-
rs0必须与 MongoDB 实际初始化的 replica set 名称一致(可通过rs.status()在 mongo shell 中确认) - 如果用了认证,用户名密码要 URL 编码(如
@→%40,/→%2F),否则解析失败 - 不推荐混用
host+port+database和uri—— 两者冲突时以uri为准,但显式指定易引发配置歧义
@Transactional 方法内只能用 MongoTemplate,不能混用 MongoRepository
Spring Data MongoDB 的 MongoRepository 在事务中存在隐式 Session 绑定问题:它可能复用非事务性 ClientSession,导致部分操作脱离事务上下文。实测中常见现象是 —— save() 成功,但后续 delete() 不回滚。
- 事务方法内统一使用
MongoTemplate,并通过withTransaction()显式控制(更可控)或依赖 Spring AOP 的@Transactional(需确保上面所有配置到位) - 若坚持用 Repository,必须确认其底层调用的是同一个
MongoDatabaseFactory实例,且未被自定义MongoOperations覆盖 - 避免在事务方法里调用另一个
@TransactionalService 方法 —— MongoDB 事务不支持嵌套,第二层注解会被忽略,无警告也无错误 - 事务方法签名不能是
void;返回void时异常仍可回滚,但 Spring AOP 可能因代理机制失效,建议统一返回具体类型(如User)
mongo --eval "rs.status()" 和日志里是否打印了 Using MongoTransactionManager。

















