根本原因是spring未找到mongodb连接工厂导致mongotemplate实例化失败;需确认引入spring-boot-starter-data-mongodb依赖、正确配置uri或host/port、自定义mongoclient时加@primary注解。

Spring Boot 项目里怎么配 MongoTemplate 才不报 BeanCreationException
根本原因是 Spring 没找到 MongoDB 连接工厂,MongoTemplate 实例化失败。别急着写配置类,先确认依赖和自动配置是否生效。
- 确保引入了
spring-boot-starter-data-mongodb,不是mongo-java-driver或mongodb-driver-sync单独包(Spring Boot 2.7+ 已弃用老驱动) -
application.yml中必须有spring.data.mongodb.uri或spring.data.mongodb.host+spring.data.mongodb.port,缺一不可;只配host不配port会默认连 27017,但若 MongoDB 启在非标端口(比如 27018),就会静默失败 - 如果用了自定义
MongoClient(比如加了 SSL 或认证),务必用@Primary标记你的MongoClientBean,否则 Spring Boot 的自动配置会和你写的冲突,导致MongoTemplate拿到空连接
MongoTemplate 查询时为什么查不到数据,但 mongo shell 能查到
最常见的是数据库名、集合名拼写不一致,或没指定正确 DatabaseName —— MongoTemplate 默认操作的是配置里 uri 中指定的库,不是你 shell 当前所在的库。
- 检查
spring.data.mongodb.database配置项是否和实际库名完全一致(区分大小写,且不能带空格或特殊字符) - 用
mongoTemplate.getDb().getName()打印当前操作的库名,确认是否是你预期的 - 查询时若用
mongoTemplate.findAll(..., "collection_name"),这个集合名必须存在且大小写完全匹配;MongoDB 默认不校验集合是否存在,所以错写成"user"写成"users"也不会报错,只是返回空列表 - 注意:如果用
@Document(collection = "xxx")注解实体类,但运行时又手动指定集合名,两个名字不一致会导致写入 A 集合、查 B 集合
用 Query 和 Criteria 构建条件时,$regex 和 like 怎么写才不出错
Criteria.regex() 是最安全的写法,手拼 $regex 对象容易漏掉 $options 或写错字段路径。
- 模糊匹配推荐写法:
Criteria.where("name").regex(".*张.*", "i"),第二个参数"i"表示忽略大小写;不要写成Pattern.compile("张", Pattern.CASE_INSENSITIVE),因为Criteria.regex(Pattern)在某些 Spring Data 版本中不支持编译后模式 - 字段含点号(如
address.city)必须用引号包裹:Criteria.where("address.city").is("Beijing"),不能写成address.city字面量 -
Criteria.andOperator()套太多层容易逻辑混乱,优先拆成多个and链式调用,比如where("a").is(1).and("b").gt(10) - 注意 null 值处理:
where("status").is(null)查的是值为null的文档,不是字段缺失;要查字段不存在得用exists(false)
为什么 MongoTemplate.save() 有时覆盖整条记录,有时只更新部分字段
这是由 ID 是否存在决定的:save() 底层是「有 _id 就 upsert,无 _id 就 insert」,它不等价于 SQL 的 UPDATE,也不是 updateFirst()。
- 实体类必须有
@Id字段(类型建议用String或ObjectId),且该字段在插入前已赋值;否则每次都会生成新_id,变成重复插入 - 想局部更新请改用
mongoTemplate.updateFirst(query, update, clazz),其中update用Update.update("field", value)构造 -
save()会把整个对象序列化后写入,未设置的字段(Java 中为null)也会被存为null,覆盖原有值;而updateFirst()只动你明确set()的字段 - 如果实体类字段加了
@Field(targetType = FieldType.STRING)等类型提示,但数据库里对应字段是int,save()可能静默转成字符串,查的时候类型对不上
真正麻烦的不是配不通,而是配通了但读写行为和预期不一致——比如 save() 覆盖、正则不生效、库名大小写搞混。这些地方没有错误日志,只有数据不对劲,得靠打印 mongoTemplate.getDb().getName() 和 query.toString() 来确认实际执行了什么。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











