在业务系统里,除了规整的用户信息、订单记录这类结构化数据,还经常遇到字段不固定的数据,比如商品详情页的动态属性、日志埋点信息、用户行为轨迹等。这类数据如果硬塞进MySQL,要么建一堆扩展字段表,要么把JSON序列化成字符串存TEXT字段,查询和维护都很别扭。MongoDB作为文档型数据库,存储结构与JSON天然契合,配合Spring Boot的spring-data-mongodb模块,可以让开发体验和写JPA几乎一样顺手。这篇文章就来完整走一遍整合流程,并覆盖实际开发中最常用的操作姿势。

环境准备与连接配置
首先创建一个Spring Boot项目,在pom.xml中引入MongoDB的starter依赖。使用starter的好处是它已经帮你把版本锁定好了,不需要自己去处理spring-data-mongodb和mongo-java-driver之间的版本兼容问题。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>接着在application.yml中配置连接信息。最简单的形式是直接写uri,如果需要指定用户名密码和认证库,也可以把uri展开成host、port、username、password等独立配置项。注意格式必须写对,密码中包含特殊字符时要进行URL编码,否则启动时会直接抛出连接异常。
spring:
data:
mongodb:
uri: mongodb://root:123456@192.168.0.1:27017/testdb?authSource=admin配置完成后,Spring Boot会自动创建一个MongoTemplate bean注入到容器中,你可以直接在测试类里用它执行一次简单的插入操作,验证连通性。如果本地没有MongoDB环境,推荐用Docker快速起一个:docker run -d -p 27017:27017 --name mongo mongo,几分钟就能搞定。
实体映射与常用注解
和JPA类似,spring-data-mongodb通过注解把Java对象映射成MongoDB的文档。最核心的几个注解需要先弄清楚。
@Document标注在类上,指定该实体对应的集合名称,类似MySQL的表。如果不指定,默认用类名首字母小写。@Id标注主键字段,对应MongoDB的_id字段,类型用String时MongoDB会自动生成ObjectId。@Field可以自定义字段名,@Indexed用于创建索引,@Transient表示该字段不参与持久化。
@Document(collection = "article")
public class Article {
@Id
private String id;
@Field("title")
private String title;
private String author;
private String content;
private List<String> tags;
@Transient
private String tempValue;
// 省略getter和setter
}有一点值得强调:MongoDB的文档结构是灵活的,同一个集合中不同文档的字段可以不一样。但在Java侧仍然需要一个固定的实体类来接收数据。如果业务上字段确实完全不固定,可以把动态部分声明成Map<String, Object>类型,或者直接操作Document对象,牺牲一点类型安全换取灵活性。
使用MongoTemplate进行增删改查
MongoTemplate是操作MongoDB最灵活的方式,适合复杂查询场景。插入和查询的写法都很直观。
@Service
public class ArticleService {
@Autowired
private MongoTemplate mongoTemplate;
public void saveArticle(Article article) {
mongoTemplate.save(article);
}
public Article findById(String id) {
return mongoTemplate.findById(id, Article.class);
}
public List<Article> findByAuthor(String author) {
Query query = new Query(Criteria.where("author").is(author));
return mongoTemplate.find(query, Article.class);
}
public void deleteById(String id) {
Query query = new Query(Criteria.where("id").is(id));
mongoTemplate.remove(query, Article.class);
}
}模糊查询用正则表达式实现,相当于SQL里的LIKE。Criteria提供了丰富的条件构造方法,gt、lt、in、regex等基本覆盖日常需求,多个条件可以用and串联,或用orOperator组合或关系。
// 模糊匹配标题并按创建时间倒序,跳过前20条取10条
Query query = new Query();
query.addCriteria(Criteria.where("title").regex(".*" + keyword + ".*"));
query.with(Sort.by(Sort.Direction.DESC, "createTime"));
query.skip(20).limit(10);
List<Article> list = mongoTemplate.find(query, Article.class);更新操作推荐使用Update配合UpdateResult判断影响行数。updateFirst只更新匹配的第一条,updateMulti更新所有匹配的文档,upsert则在不存在时执行插入。
Repository接口方式与分页查询
如果只是常规的增删改查,更省事的方式是继承MongoRepository接口,方法名按约定生成,连实现类都不用写。它同时自带了分页能力,传入Pageable参数即可返回Page对象,包含总记录数和分页数据。
public interface ArticleRepository extends MongoRepository<Article, String> {
List<Article> findByAuthor(String author);
Page<Article> findByTitleContaining(String keyword, Pageable pageable);
}// 调用分页查询
PageRequest pageRequest = PageRequest.of(0, 10, Sort.by("createTime").descending());
Page<Article> page = articleRepository.findByTitleContaining("Spring", pageRequest);
long total = page.getTotalElements();
List<Article> content = page.getContent();两种方式的选择标准很简单:固定模式的简单查询用Repository,代码量少且可读性好;涉及复杂条件组合、聚合统计、动态拼接查询时用MongoTemplate。两者并不冲突,实际项目里通常混合使用,Service层注入各自需要的依赖即可。
索引优化与实战注意事项
MongoDB在没有索引的情况下执行查询会触发全集合扫描,数据量一大性能会急剧下降。常用的查询字段一定要建索引,可以在实体类上加@Indexed,也可以在Navicat或mongosh中手动创建。组合查询场景用@CompoundIndex建立复合索引,注意字段的先后顺序会影响索引命中。
@Document(collection = "article")
@CompoundIndex(name = "author_title_idx", def = "{'author': 1, 'title': -1}")
public class Article {
// ...
}还有几个容易踩的坑提醒一下。第一,_id字段在MongoDB中类型是ObjectId,如果实体类里声明为String,查询时直接传字符串也能命中,框架会做转换,但如果手动存了自定义字符串ID,要保证类型一致。第二,MongoDB单个文档有16MB的大小限制,超大内容不要往一个文档里塞,应拆分或改用GridFS存储。第三,生产环境务必开启副本集并配置连接池参数,单节点模式既不安全也没有高可用能力。第四,事务方面,MongoDB 4.0之后支持多文档事务,但需要副本集环境,单机下使用@Transactional会直接报错,这一点和MySQL的使用习惯差别很大。
整体来看,Spring Boot整合MongoDB的上手成本很低,自动配置帮开发者省去了大量样板代码。只要把实体映射、两种数据访问方式的适用场景以及索引设计这几个核心点掌握好,处理非结构化文档数据时就能得心应手。对于日志分析、内容管理、商品动态属性这类字段多变的场景,MongoDB配合Spring Boot是一套非常值得采用的方案。
Spring BootMongoDB文档存储修改时间:2026-09-04 22:10:46