Spring Boot 2.2+才支持MongoDB原生事务,需满足:版本≥2.2.0、副本集部署、显式配置MongoTransactionManager、事务内操作限于同库同分片且使用同一MongoTemplate。

Spring Boot 2.2+ 才支持 MongoDB 原生事务
MongoDB 事务从 4.0 开始支持,但 Spring Boot 直到 2.2.0 版本才通过 MongoTransactionManager 提供完整集成。如果你用的是 2.1.x 或更早,@Transactional 注解对 MongoDB 完全无效——它不会报错,但也不会开启事务,数据会直接提交。
- 检查版本:
spring-boot-starter-data-mongodb必须 ≥2.2.0,对应底层spring-data-mongodb≥2.2.0.RELEASE - 确保 MongoDB 部署为副本集(replica set)或分片集群(sharded cluster),单节点 standalone 模式不支持事务
- 连接字符串必须显式指定 replica set 名称,例如:
mongodb://localhost:27017/mydb?replicaSet=rs0
必须手动配置 MongoTransactionManager
Spring Boot 不会自动配置 MongoDB 的事务管理器,哪怕你加了 @EnableTransactionManagement 也不行。缺了这一步,@Transactional 就只对 JPA/DataSource 生效,MongoDB 被完全忽略。
- 在配置类中声明一个
@Bean:@Bean public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } - 注意参数类型是
MongoDatabaseFactory(Spring Data MongoDB 3.0+ 推荐),不是旧版的MongoTemplate或Mongo - 如果项目里同时用了 JPA 和 MongoDB,两个事务管理器必须分别命名,并在
@Transactional中用transactionManager = "xxx"显式指定
@Transactional 在 MongoDB 中的限制很实在
MongoDB 事务不是“全能替代”,它有明确边界:只能跨 collection 读写,但不能跨数据库、不能包含某些操作(如 $out、$merge)、也不能在分片集群中跨分片事务(除非所有操作落在同一分片上)。
- 事务内所有操作必须使用同一个
MongoTemplate实例(即同一个MongoDatabaseFactory),混用不同 template 会导致事务失效 - 事务超时默认是 60 秒,可通过
@Transactional(timeout = 30)调整,但 MongoDB 服务端也有transactionLifetimeLimitSeconds配置,两者需匹配 - 异常必须传播出方法边界才能回滚;捕获后吞掉异常(比如 try-catch + log),事务就认为“成功”而提交
- 事务块内不要调用非事务性外部服务(如 HTTP 请求、Redis 写入),否则无法保证最终一致性
事务开启失败时,错误信息往往藏在底层驱动日志里
事务没生效,通常不会抛出明显异常。最常见的情况是:连接没走 replica set、事务管理器没注册、或者方法没被 Spring AOP 正确代理(比如自调用、非 public 方法)。
- 打开 DEBUG 日志:
logging.level.org.springframework.transaction=DEBUG,看是否打印Creating new transaction和Initiating transaction commit - 检查 MongoDB 日志,搜索
transaction或abort,确认服务端是否收到事务命令 - 用
MongoTemplate.executeInTransaction()手动方式做一次测试,绕过 AOP,能快速验证底层是否通畅:template.executeInTransaction(tmpl -> { tmpl.insert(new User("a"), "users"); tmpl.insert(new Order("o1"), "orders"); return true; });










