Spring Boot 3 与 MongoDB:构建高性能 NoSQL 应用的终极指南
1. 引言:为什么选择 Spring Boot 3 和 MongoDB?
在现代应用开发中,快速构建高效、可扩展的系统是开发者的核心目标。Spring Boot 作为 Java 生态中最流行的微服务框架之一,与 MongoDB 这款强大的 NoSQL 数据库结合,能够为开发者提供一个灵活、高性能的解决方案。
-
快速开发:Spring Boot 提供了开箱即用的功能(例如自动配置、嵌入式服务器),而 Spring Data MongoDB 进一步简化了 MongoDB 的操作。开发者只需定义实体类和 Repository 接口,就能实现对 MongoDB 的 CRUD 操作,大幅减少样板代码。
-
处理非结构化数据:在许多现代应用中,数据结构可能随着业务需求不断变化(例如电商平台的商品属性、社交平台的用户动态)。MongoDB 的文档模型允许动态调整 Schema,而 Spring Boot 提供了强大的对象映射能力(通过
@Document
和@Field
注解),让开发者可以轻松应对这种灵活性。 -
构建高性能微服务:Spring Boot 3 的微服务支持(结合 Spring Cloud)和 MongoDB 的分布式能力相得益彰。开发者可以构建松耦合的微服务架构,每个服务使用独立的 MongoDB 数据库实例,通过分片和副本集实现高可用性和负载均衡。
-
支持多样化的业务场景:无论是实时分析(通过 MongoDB 聚合管道)、文件存储(通过 GridFS),还是高并发读写(通过索引和连接池优化),Spring Boot 和 MongoDB 的组合都能提供强大的支持。
通过集成 Spring Boot 3 和 MongoDB,开发者可以在快速开发和高效运行之间找到平衡,构建出既灵活又高性能的现代应用。接下来,我们将从环境搭建开始,逐步展示如何实现这一集成,并挖掘两者的潜力。
2. 环境搭建:从零开始集成 MongoDB
2.1 MongoDB 安装与测试
这一步不在本文详细描述,可以去网上搜索一下相关资料
- 本地安装 MongoDB 或使用 Docker 部署
- 使用 MongoDB Compass 或命令行测试连接
2.2 Spring Boot 项目初始化
本文使用的是SpringBoot3.4.4版本。
创建项目的相关配置信息如下:
2.3 依赖配置
- pom.xml文件详细信息如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.kedaya</groupId>
<artifactId>springboot3-mongodb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot3-mongodb</name>
<description>springboot3-mongodb</description>
<properties>
<java.version>17</java.version>
<mapstruct.version>1.5.5.Final</mapstruct.version>
</properties>
<dependencies>
<!--MongoDB-start依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${project.parent.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- application.properties相关配置信息如下
spring.application.name=springboot3-mongodb
server.port=8080
# MongoDB配置信息 - 开发环境
spring.data.mongodb.host=xxx.xxx.xxx.xx
spring.data.mongodb.port=27017
spring.data.mongodb.database=数据库名称
spring.data.mongodb.username=username
spring.data.mongodb.password=password
# 通用MongoDB配置
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.auto-index-creation=true
# Jackson配置
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jackson.default-property-inclusion=NON_NULL
# 日志配置
logging.level.root=INFO
logging.level.com.kedaya=DEBUG
logging.level.org.springframework.data.mongodb=DEBUG
3. 核心功能:使用 Spring Data MongoDB 实现 CRUD
3.1 定义数据模型
- 创建实体类(
@Document
注解) - 字段映射(
@Id
、@Field
等)
下面我们创建一个用户实体数据模型
package com.kedaya.springboot3mongodb.model.entity;
import com.kedaya.springboot3mongodb.constant.MongoConstant;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.time.LocalDateTime;
/**
* 用户实体类
*/
@Data
@Document(collection = MongoConstant.Collection.USER)
public class UserEntity {
/**
* 用户主键
*/
@Id
private String id;
/**
* 用户名
*/
@Indexed(unique = true)
private String username;
/**
* 用户密码
*/
private String password;
/**
* 用户邮箱
*/
@Indexed
private String email;
/**
* 用户昵称
*/
private String nickname;
/**
* 用户年龄
*/
private Integer age;
/**
* 用户头像
*/
private String avatar;
/**
* 创建时间
*/
@Field(MongoConstant.Field.CREATE_TIME)
private LocalDateTime createTime;
/**
* 更新时间
*/
@Field(MongoConstant.Field.UPDATE_TIME)
private LocalDateTime updateTime;
/**
* 是否删除
*/
@Field(MongoConstant.Field.DELETED)
private Boolean deleted;
}
3.2 实现 Repository
- 使用
MongoRepository
接口自动生成 CRUD 方法 - 自定义查询方法(例如
findByUsername
)
接下来我们来创建一个UserRepository
package com.kedaya.springboot3mongodb.repository;
import com.kedaya.springboot3mongodb.model.entity.UserEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
/**
* 用户存储库接口
*/
@Repository
public interface UserRepository extends MongoRepository<UserEntity, String> {
/**
* 根据用户名查找用户
*/
Optional<UserEntity> findByUsername(String username);
/**
* 根据邮箱查找用户
*/
Optional<UserEntity> findByEmail(String email);
/**
* 根据年龄范围查找用户
*/
List<UserEntity> findByAgeBetween(Integer minAge, Integer maxAge);
/**
* 查找未删除的用户
*/
@Query("{'deleted': false}")
List<UserEntity> findAllNotDeleted();
}
3.3 控制器层实现
- 创建 REST API(
@RestController
) - 实现增删改查操作(
POST
、GET
、PUT
、DELETE
)
接下来我们创建UserController
控制器
package com.kedaya.springboot3mongodb.controller;
import com.kedaya.springboot3mongodb.model.dto.UserDTO;
import com.kedaya.springboot3mongodb.model.vo.UserVO;
import com.kedaya.springboot3mongodb.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 用户控制器
*/
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/**
* 创建用户
*/
@PostMapping
public ResponseEntity<UserVO> createUser(@RequestBody UserDTO userDTO) {
UserVO createdUser = userService.createUser(userDTO);
return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
}
/**
* 更新用户
*/
@PutMapping("/{id}")
public ResponseEntity<UserVO> updateUser(@PathVariable String id, @RequestBody UserDTO userDTO) {
UserVO updatedUser = userService.updateUser(id, userDTO);
return ResponseEntity.ok(updatedUser);
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable String id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
/**
* 获取单个用户
*/
@GetMapping("/{id}")
public ResponseEntity<UserVO> getUserById(@PathVariable String id) {
UserVO user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
/**
* 根据用户名查询用户
*/
@GetMapping("/username/{username}")
public ResponseEntity<UserVO> getUserByUsername(@PathVariable String username) {
UserVO user = userService.getUserByUsername(username);
return ResponseEntity.ok(user);
}
/**
* 获取所有用户
*/
@GetMapping
public ResponseEntity<List<UserVO>> getAllUsers() {
List<UserVO> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
/**
* 根据年龄范围查询用户
*/
@GetMapping("/age")
public ResponseEntity<List<UserVO>> getUsersByAgeRange(
@RequestParam Integer minAge,
@RequestParam Integer maxAge) {
List<UserVO> users = userService.getUsersByAgeRange(minAge, maxAge);
return ResponseEntity.ok(users);
}
}
3.4 测试 CRUD 功能
- 使用 Postman 或 cURL 测试 API
- 验证 MongoDB 数据库中的数据变化
4. 高级特性:挖掘 MongoDB 的潜力
本章节详细介绍MongoDB的高级特性在Spring Boot 3项目中的应用,通过实际示例帮助开发者充分利用MongoDB的强大功能。
4.1 索引优化
索引是提高查询性能的关键。在MongoDB中,合理使用索引可以显著提升查询速度。
4.1.1 索引类型及定义方式
package com.kedaya.springboot3mongodb.model.entity;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
@Data
@Document(collection = "products")
@CompoundIndexes({
@CompoundIndex(name = "category_price", def = "{'category': 1, 'price': -1}")
})
public class ProductEntity {
@Id
private String id;
@NotBlank(message = "商品名称不能为空")
@Indexed(unique = true)
private String name;
@NotNull(message = "价格不能为空")
@Positive(message = "价格必须大于0")
private BigDecimal price;
@Indexed
private String category;
private String description;
@Indexed(background = true)
private LocalDateTime createTime;
}
4.1.2 索引性能测试
可以使用以下方法验证索引效果:
// 比较有索引和无索引的查询效率
db.products.find({category: "手机"}).explain("executionStats")
4.1.3 索引使用最佳实践
- 为频繁查询的字段创建索引
- 避免过多索引,会影响写入性能
- 对于复合查询,考虑创建复合索引
- 使用
background=true
创建后台索引避免索引创建阻塞数据库操作
4.2 聚合管道
聚合管道提供了强大的数据处理能力,可以进行复杂的数据分析。
4.2.1 聚合操作基本组件
// ProductAggregationService.java
public List<Map> getAveragePriceByCategory() {
// 1. 定义分组操作
GroupOperation groupByCategory = Aggregation.group("category")
.avg("price").as("averagePrice")
.count().as("productCount");
// 2. 定义排序操作
SortOperation sortByAvgPrice = Aggregation.sort(Sort.Direction.DESC, "averagePrice");
// 3. 指定要包含的字段
ProjectionOperation projectFields = Aggregation.project()
.and("_id").as("category")
.and("averagePrice").as("averagePrice")
.and("productCount").as("productCount");
// 4. 创建聚合管道
Aggregation aggregation = Aggregation.newAggregation(
groupByCategory,
sortByAvgPrice,
projectFields
);
// 5. 执行聚合操作
AggregationResults<Map> results = mongoTemplate.aggregate(
aggregation, "products", Map.class);
return results.getMappedResults();
}
4.2.2 常用聚合操作
- match: 筛选文档
- group: 分组聚合
- project: 投影字段
- sort: 排序
- limit: 限制结果数量
- skip: 跳过结果
4.2.3 聚合管道示例
// 按价格范围分组统计产品数量
public List<Map> countProductsByPriceRange() {
ProjectionOperation projectFields = Aggregation.project("price")
.and(ConditionalOperators.when(Criteria.where("price").lt(new BigDecimal(100)))
.then("便宜")
.otherwise(ConditionalOperators.when(Criteria.where("price").lt(new BigDecimal(500)))
.then("适中")
.otherwise("昂贵")))
.as("priceRange");
GroupOperation groupByPriceRange = Aggregation.group("priceRange")
.count().as("count");
Aggregation aggregation = Aggregation.newAggregation(
projectFields,
groupByPriceRange
);
AggregationResults<Map> results = mongoTemplate.aggregate(
aggregation, "products", Map.class);
return results.getMappedResults();
}
4.3 事务支持
从MongoDB 4.0开始,MongoDB支持多文档事务,Spring Boot 3提供了与之集成的事务支持。
4.3.1 事务配置
@Configuration
public class MongoTransactionConfig {
@Bean
public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}
4.3.2 注解式事务
@Service
public class TransactionalProductService {
@Autowired
private ProductRepository productRepository;
@Transactional
public List<Product> batchCreateProducts(List<Product> products) {
// 在这个方法中的所有数据库操作都将在一个事务中
return productRepository.saveAll(products);
}
@Transactional
public Product replaceProduct(String oldProductId, Product newProduct) {
// 删除旧产品
productRepository.deleteById(oldProductId);
// 创建新产品
return productRepository.save(newProduct);
// 如果任一操作失败,两个操作都会回滚
}
}
4.3.3 编程式事务
public void updateProductPrices(List<String> productIds, BigDecimal increaseAmount) {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(status -> {
try {
for (String id : productIds) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("产品未找到:" + id));
BigDecimal newPrice = product.getPrice().add(increaseAmount);
product.setPrice(newPrice);
productRepository.save(product);
}
return null;
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
});
}
4.3.4 事务注意事项
- 需要副本集:MongoDB事务必须在副本集环境中使用
- 性能影响:事务会降低性能,不要在不必要的场景使用
- 锁定:事务会锁定相关文档,可能导致阻塞
- 超时设置:设置合理的事务超时时间
- 重试机制:考虑为事务添加重试机制
4.4 GridFS 存储大文件
GridFS是MongoDB存储大文件(>16MB)的方案,将文件分块存储,支持高效读写。
4.4.1 GridFS服务实现
@Service
public class GridFsService {
@Autowired
private GridFsTemplate gridFsTemplate;
@Autowired
private GridFsOperations gridFsOperations;
/**
* 上传文件到GridFS
*/
public String uploadFile(MultipartFile file, String filename, Map<String, String> metadata) throws IOException {
if (metadata == null) {
metadata = new HashMap<>();
}
metadata.put("contentType", file.getContentType());
metadata.put("size", String.valueOf(file.getSize()));
InputStream inputStream = file.getInputStream();
ObjectId objectId = gridFsTemplate.store(
inputStream,
filename,
file.getContentType(),
metadata);
inputStream.close();
return objectId.toString();
}
/**
* 根据ID获取文件
*/
public GridFsResource getFileById(String fileId) {
GridFSFile gridFSFile = gridFsTemplate.findOne(
new Query(Criteria.where("_id").is(new ObjectId(fileId))));
if (gridFSFile == null) {
return null;
}
return gridFsOperations.getResource(gridFSFile);
}
}
4.4.2 文件上传下载API
@RestController
@RequestMapping("/files")
public class FileController {
@Autowired
private GridFsService gridFsService;
@PostMapping("/upload")
public ResponseEntity<Map<String, Object>> uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "filename", required = false) String filename) {
try {
if (filename == null || filename.isEmpty()) {
filename = file.getOriginalFilename();
}
Map<String, String> metadata = new HashMap<>();
metadata.put("uploadTime", String.valueOf(System.currentTimeMillis()));
String fileId = gridFsService.uploadFile(file, filename, metadata);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("fileId", fileId);
response.put("filename", filename);
return ResponseEntity.ok(response);
} catch (IOException e) {
Map<String, Object> response = new HashMap<>();
response.put("success", false);
response.put("error", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
@GetMapping("/download/{fileId}")
public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String fileId) {
try {
GridFsResource resource = gridFsService.getFileById(fileId);
if (resource == null || !resource.exists()) {
return ResponseEntity.notFound().build();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(resource.getContentType()));
headers.setContentDispositionFormData("attachment", resource.getFilename());
return ResponseEntity.ok()
.headers(headers)
.body(new InputStreamResource(resource.getInputStream()));
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
}
4.4.3 GridFS 使用场景与建议
- 适用场景:存储大于16MB的文件,如图片、文档、视频等
- 元数据管理:利用元数据实现文件分类和搜索
- 流式处理:支持流式读写,不必一次加载整个文件
- 性能优化:对于频繁访问的小文件,考虑直接存储为Binary数据
- 备份策略:为GridFS集合制定单独的备份策略
5. 性能优化:让应用更快更稳
高级特性的使用需要注意性能影响,建议针对实际应用场景进行性能测试和调优:
- 使用MongoDB Compass观察查询执行计划
- 监控查询性能和资源使用情况
- 设置适当的写入关注级别和读取偏好
- 针对高频查询优化索引结构
- 大量数据场景下考虑分片
5.1 连接池配置
- 配置 MongoDB 客户端的连接池
package com.kedaya.springboot3mongodb.config;
import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.MongoTransactionManager;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import static com.mongodb.MongoCredential.createCredential;
import static java.util.Collections.singletonList;
/**
* MongoDB配置类
*/
@Configuration
public class MongoConfig {
@Autowired
private MongoProperties mongoProperties;
/**
* 创建MongoDB客户端,配置连接池信息
* @return
* @throws Exception
*/
@Bean
public MongoClient mongoClient() throws Exception {
String mongoUri = buildMongoUri();
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(mongoUri))
.applyToClusterSettings(setting -> {
setting.hosts(singletonList(new ServerAddress(mongoProperties.getHost(), mongoProperties.getPort())));
})
// 配置连接池信息
.applyToConnectionPoolSettings(builder -> builder
.maxSize(100) // 最大连接数
.minSize(10) // 最小连接数
.maxWaitTime(120000, java.util.concurrent.TimeUnit.MILLISECONDS) // 最大等待时间
.maxConnectionIdleTime(300000, java.util.concurrent.TimeUnit.MILLISECONDS) // 最大空闲时间
.maxConnectionLifeTime(0, java.util.concurrent.TimeUnit.MILLISECONDS) // 最大存活时间
)
.build();
return MongoClients.create(settings);
}
@Bean
public MongoTemplate mongoTemplate(MongoClient mongoClient) {
return new MongoTemplate(mongoClient, mongoProperties.getDatabase());
}
private String buildMongoUri() throws Exception {
// 如果配置了 uri,直接使用
if (mongoProperties.getUri() != null) {
return mongoProperties.getUri();
}
// 否则手动构造
String host = mongoProperties.getHost() != null ? mongoProperties.getHost() : "localhost";
int port = mongoProperties.getPort() != 0 ? mongoProperties.getPort() : 27017;
String database = mongoProperties.getDatabase();
String username = mongoProperties.getUsername();
String password = String.valueOf(mongoProperties.getPassword());
String authDatabase = mongoProperties.getAuthenticationDatabase() != null
? mongoProperties.getAuthenticationDatabase()
: database;
if (username != null && !username.isEmpty() && password != null && !password.isEmpty()) {
String encodedUsername = URLEncoder.encode(username, StandardCharsets.UTF_8.toString());
String encodedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8.toString());
return String.format("mongodb://%s:%s@%s:%d/%s?authSource=%s",
encodedUsername, encodedPassword, host, port, database, authDatabase);
} else {
return String.format("mongodb://%s:%d/%s", host, port, database);
}
}
}
- 分析连接池对性能的影响
5.2 查询优化
- 避免全表扫描,使用覆盖索引
- 使用
explain()
分析查询性能
5.3 缓存集成
- 结合 Spring Cache(
@Cacheable
)减少数据库查询 - 示例:使用 Redis 作为缓存层
6. 最佳实践与注意事项
- 数据模型设计:避免嵌套过深,合理使用引用
- 异常处理:处理 MongoDB 连接失败、超时等问题
- 日志管理:使用 SLF4J 记录 MongoDB 操作日志
- 安全性:配置 MongoDB 认证和加密传输
- 部署建议:生产环境中 MongoDB 的副本集和分片