MongoDB与SpringBoot概述
什么是MongoDB?
MongoDB是一个基于分布式文件存储的NoSQL数据库,采用文档型数据模型(BSON格式,类似JSON)。与传统关系型数据库相比:
特性 | MongoDB | 传统关系型数据库 |
---|---|---|
数据模型 | 文档型 | 表结构 |
扩展方式 | 水平扩展(分片) | 垂直扩展 |
查询语言 | MQL | SQL |
事务支持 | 4.0+版本支持多文档 | 完全支持 |
适用场景 | 大数据量、高并发、灵活模式 | 强一致性、复杂关系 |
为什么选择SpringBoot整合MongoDB?
- 简化配置:Spring Data MongoDB提供自动配置
- 丰富的模板:MongoTemplate和Repository支持
- 对象映射:通过注解实现POJO与文档映射
- 事务支持:简化分布式事务管理
- 生态整合:与Spring其他组件无缝协作
环境准备与基础配置
1. 依赖引入
<dependencies>
<!-- Spring Boot Starter for MongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- 如果需要验证等功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Lombok简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
2. 基础配置详解
application.yml
配置示例:
spring:
data:
mongodb:
# 单机模式配置
host: localhost
port: 27017
database: blog_db
username: blog_user # 可选
password: securepwd # 可选
# 连接池配置
authentication-database: admin # 认证数据库
auto-index-creation: true # 自动创建索引
# 副本集配置示例
# uri: mongodb://user:pass@host1:port1,host2:port2/database?replicaSet=rs0
# 连接池配置
connection-pool:
max-size: 100 # 最大连接数
min-size: 10 # 最小连接数
max-wait-time: 30000 # 最大等待时间(ms)
配置项解析表:
配置项 | 说明 | 默认值 | 建议值 |
---|---|---|---|
host | MongoDB服务器地址 | localhost | 根据环境配置 |
port | MongoDB端口 | 27017 | - |
database | 默认数据库 | - | 必填 |
auto-index-creation | 是否自动创建索引 | false | 开发环境true,生产环境false |
max-size | 连接池最大连接数 | 100 | 根据并发量调整 |
min-size | 连接池最小连接数 | 0 | 10-20 |
max-wait-time | 获取连接最大等待时间(ms) | 120000 | 30000-60000 |
3. 实体类映射
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.util.Date;
import java.util.List;
@Document(collection = "users") // 指定集合名称
@Data // Lombok注解,自动生成getter/setter等
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id // 主键标识
private String id;
@Indexed(unique = true) // 唯一索引
private String username;
@Field("pwd") // 指定文档中字段名
private String password;
private Integer age;
@Indexed // 普通索引
private Date createTime;
private List<String> hobbies; // 数组类型
private Address address; // 嵌套文档
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String city;
private String street;
private String zipCode;
}
注解说明表:
注解 | 作用 | 示例 |
---|---|---|
@Document | 标识该类对应MongoDB文档 | @Document(collection=“users”) |
@Id | 标识主键字段 | @Id private String id; |
@Field | 指定文档字段名 | @Field(“pwd”) private String password; |
@Indexed | 创建索引 | @Indexed(unique=true) |
@Transient | 不持久化到数据库 | @Transient private String temp; |
@DBRef | 引用其他文档 | @DBRef private Department dept; |
核心CRUD操作
1. MongoTemplate基础操作
@SpringBootTest
public class MongoTemplateTest {
@Autowired
private MongoTemplate mongoTemplate;
// 插入文档
@Test
public void testInsert() {
User user = new User(null, "user1", "123456", 25, new Date(),
Arrays.asList("reading", "swimming"),
new Address("Beijing", "Main St", "100001"));
// insert方法: 插入单个文档
User insertedUser = mongoTemplate.insert(user); // 返回插入后的对象(包含生成的id)
System.out.println("Inserted user id: " + insertedUser.getId());
// insertAll方法: 批量插入
List<User> users = Arrays.asList(
new User(null, "user2", "111111", 30, new Date(), Arrays.asList("hiking"),
new Address("Shanghai", "Nanjing Rd", "200001")),
new User(null, "user3", "222222", 28, new Date(), Arrays.asList("music"),
new Address("Guangzhou", "Zhongshan Rd", "510000"))
);
Collection<User> insertedUsers = mongoTemplate.insertAll(users);
insertedUsers.forEach(u -> System.out.println("Inserted: " + u.getUsername()));
}
// 查询文档
@Test
public void testQuery() {
// 1. 根据ID查询
User user = mongoTemplate.findById("5f8d8a7c6b3a1d2e3c4b5a6", User.class);
System.out.println("Find by ID: " + user);
// 2. 查询所有
List<User> allUsers = mongoTemplate.findAll(User.class);
allUsers.forEach(u -> System.out.println("All users: " + u.getUsername()));
// 3. 条件查询
Query query = new Query(Criteria.where("age").gt(25).lt(30)
.and("hobbies").in("reading"));
List<User> users = mongoTemplate.find(query, User.class);
users.forEach(u -> System.out.println("Conditional query: " + u.getUsername()));
}
// 更新文档
@Test
public void testUpdate() {
// 1. 更新第一个匹配的文档
Query query = new Query(Criteria.where("username").is("user1"));
Update update = new Update().set("age", 26).inc("loginCount", 1);
UpdateResult result = mongoTemplate.updateFirst(query, update, User.class);
System.out.println("Matched: " + result.getMatchedCount() +
", Modified: " + result.getModifiedCount());
// 2. 更新所有匹配的文档
Update multiUpdate = new Update().set("active", true);
UpdateResult multiResult = mongoTemplate.updateMulti(
new Query(Criteria.where("age").gt(25)),
multiUpdate,
User.class
);
// 3. upsert操作(不存在则插入)
Update upsertUpdate = new Update().setOnInsert("username", "newUser")
.set("age", 20);
UpdateResult upsertResult = mongoTemplate.upsert(
new Query(Criteria.where("username").is("newUser")),
upsertUpdate,
User.class
);
System.out.println("Upserted ID: " + upsertResult.getUpsertedId());
}
// 删除文档
@Test
public void testDelete() {
// 1. 根据ID删除
User user = mongoTemplate.findById("5f8d8a7c6b3a1d2e3c4b5a6", User.class);
if (user != null) {
DeleteResult result = mongoTemplate.remove(user);
System.out.println("Deleted count: " + result.getDeletedCount());
}
// 2. 条件删除
Query query = new Query(Criteria.where("age").lt(20));
DeleteResult multiResult = mongoTemplate.remove(query, User.class);
System.out.println("Deleted count: " + multiResult.getDeletedCount());
}
}
2. Repository方式操作
定义Repository接口:
public interface UserRepository extends MongoRepository<User, String> {
// 方法名派生查询
List<User> findByAgeBetween(int min, int max);
List<User> findByHobbiesIn(List<String> hobbies);
// 使用@Query注解
@Query("{ 'age' : { $gt: ?0, $lt: ?1 } }")
List<User> findUsersByAgeRange(int minAge, int maxAge);
// 分页查询
Page<User> findByAddressCity(String city, Pageable pageable);
// 排序查询
List<User> findByUsernameLike(String username, Sort sort);
}
Repository使用示例:
@SpringBootTest
public class RepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void testCRUD() {
// 保存(插入或更新)
User newUser = new User(null, "repoUser", "password", 30, new Date(),
Arrays.asList("coding"),
new Address("Shenzhen", "Tech Ave", "518000"));
userRepository.save(newUser);
// 查询
Optional<User> found = userRepository.findById(newUser.getId());
found.ifPresent(user -> System.out.println("Found: " + user.getUsername()));
// 派生方法查询
List<User> ageBetween = userRepository.findByAgeBetween(25, 35);
ageBetween.forEach(u -> System.out.println("Age between: " + u.getUsername()));
// 分页查询
Page<User> page = userRepository.findByAddressCity(
"Beijing",
PageRequest.of(0, 2, Sort.by("age").descending())
);
System.out.println("Total pages: " + page.getTotalPages());
page.getContent().forEach(u -> System.out.println("Page user: " + u.getUsername()));
// 删除
userRepository.deleteById(newUser.getId());
}
}
查询方法与高级查询
1. 查询构建方式对比
查询方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
MongoTemplate | 灵活,支持所有MongoDB操作 | 代码量较大 | 复杂查询、聚合操作 |
方法名派生 | 简单,无需实现 | 功能有限,方法名可能过长 | 简单条件查询 |
@Query注解 | 平衡灵活性和简洁性 | 需要学习MongoDB JSON语法 | 中等复杂度查询 |
2. 复杂查询示例
public class AdvancedQueryTest {
@Autowired
private MongoTemplate mongoTemplate;
// 1. 多条件组合查询
@Test
public void testMultiCriteria() {
Criteria criteria = new Criteria();
criteria.andOperator(
Criteria.where("age").gt(20),
Criteria.where("address.city").is("Beijing"),
Criteria.where("hobbies").size(2)
);
Query query = new Query(criteria)
.with(Sort.by(Sort.Direction.DESC, "createTime"))
.skip(0)
.limit(5);
List<User> users = mongoTemplate.find(query, User.class);
users.forEach(u -> System.out.println("Complex query result: " + u));
}
// 2. 正则表达式查询
@Test
public void testRegex() {
// 查询用户名包含"john"不区分大小写的用户
Pattern pattern = Pattern.compile("john", Pattern.CASE_INSENSITIVE);
Query query = new Query(Criteria.where("username").regex(pattern));
List<User> users = mongoTemplate.find(query, User.class);
}
// 3. 数组查询
@Test
public void testArrayQuery() {
// 查询hobbies包含"reading"和"swimming"的用户
Query query1 = new Query(Criteria.where("hobbies").all("reading", "swimming"));
// 查询hobbies数组第二个元素为"music"的用户
Query query2 = new Query(Criteria.where("hobbies.1").is("music"));
// 查询hobbies数组长度大于3的用户
Query query3 = new Query(Criteria.where("hobbies").size(3));
}
// 4. 投影查询(只返回指定字段)
@Test
public void testProjection() {
Query query = new Query(Criteria.where("age").gt(25));
query.fields()
.include("username", "age") // 包含字段
.exclude("password") // 排除字段
.elemMatch("hobbies"); // 数组元素匹配
List<User> users = mongoTemplate.find(query, User.class);
}
}
3. 地理空间查询
首先在实体类中添加地理空间信息:
@Document(collection = "places")
@Data
public class Place {
@Id
private String id;
private String name;
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private GeoJsonPoint location;
}
地理空间查询示例:
public class GeoQueryTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void testNearQuery() {
// 1. 准备测试数据
Place p1 = new Place(null, "Central Park", new GeoJsonPoint(-73.968285, 40.785091));
Place p2 = new Place(null, "Empire State", new GeoJsonPoint(-73.9857, 40.7484));
mongoTemplate.insertAll(Arrays.asList(p1, p2));
// 2. 附近查询(距离某点1000米内的地点)
Point point = new Point(-73.9667, 40.78);
Distance distance = new Distance(1, Metrics.KILOMETERS);
Query query = new Query(
Criteria.where("location").nearSphere(point).maxDistance(distance.getNormalizedValue())
);
List<Place> places = mongoTemplate.find(query, Place.class);
places.forEach(p -> System.out.println("Nearby place: " + p.getName()));
}
@Test
public void testGeoWithin() {
// 查询位于多边形区域内的地点
List<Point> polygonPoints = Arrays.asList(
new Point(-73.992787, 40.758896),
new Point(-73.961304, 40.760148),
new Point(-73.950676, 40.728669),
new Point(-73.984513, 40.728928),
new Point(-73.992787, 40.758896) // 闭合多边形
);
Query query = new Query(
Criteria.where("location").within(new GeoJsonPolygon(polygonPoints))
);
List<Place> places = mongoTemplate.find(query, Place.class);
}
}
聚合框架
MongoDB聚合框架提供了强大的数据处理能力,类似于SQL中的GROUP BY、JOIN等操作。
1. 基本聚合操作
public class AggregationTest {
@Autowired
private MongoTemplate mongoTemplate;
// 1. 统计各城市用户数量
@Test
public void testGroupBy() {
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.group("address.city").count().as("userCount"),
Aggregation.sort(Sort.Direction.DESC, "userCount"),
Aggregation.limit(10)
);
AggregationResults<Document> results = mongoTemplate.aggregate(
aggregation, "users", Document.class);
results.getMappedResults().forEach(doc -> {
System.out.println(doc.getString("_id") + ": " + doc.getInteger("userCount"));
});
}
// 2. 多阶段聚合:筛选->分组->排序
@Test
public void testMultiStageAggregation() {
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("age").gt(20)), // 阶段1: 筛选
Aggregation.group("address.city") // 阶段2: 按城市分组
.avg("age").as("avgAge")
.sum("age").as("totalAge")
.count().as("userCount"),
Aggregation.sort(Sort.Direction.DESC, "userCount"), // 阶段3: 排序
Aggregation.project() // 阶段4: 投影
.and("_id").as("city")
.and("avgAge").as("averageAge")
.and("totalAge").as("totalAge")
.and("userCount").as("count")
.andExclude("_id")
);
AggregationResults<Document> results = mongoTemplate.aggregate(
aggregation, "users", Document.class);
}
}
2. 聚合操作符详解
常用聚合阶段:
阶段 | 说明 | 等效SQL |
---|---|---|
$match | 筛选文档 | WHERE |
$group | 分组 | GROUP BY |
$sort | 排序 | ORDER BY |
$project | 投影(选择字段) | SELECT |
$limit | 限制结果数量 | LIMIT |
$skip | 跳过文档 | OFFSET |
$unwind | 展开数组 | - |
$lookup | 关联查询 | LEFT OUTER JOIN |
常用聚合表达式:
表达式 | 说明 | 示例 |
---|---|---|
$sum | 求和 | $sum: 1 (计数) |
$avg | 平均值 | a v g : " avg: " avg:"age" |
$min | 最小值 | m i n : " min: " min:"price" |
$max | 最大值 | m a x : " max: " max:"score" |
$push | 将值加入数组 | p u s h : " push: " push:"name" |
$addToSet | 将唯一值加入数组 | a d d T o S e t : " addToSet: " addToSet:"category" |
$first | 获取第一个文档值 | f i r s t : " first: " first:"timestamp" |
$last | 获取最后一个文档值 | l a s t : " last: " last:"status" |
3. 关联查询($lookup)
// 用户和订单关联查询
@Test
public void testLookup() {
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.lookup("orders", "id", "userId", "userOrders"),
Aggregation.match(Criteria.where("userOrders").not().size(0)),
Aggregation.project()
.and("username").as("name")
.and("userOrders").as("orders")
.andExclude("_id")
);
AggregationResults<Document> results = mongoTemplate.aggregate(
aggregation, "users", Document.class);
results.getMappedResults().forEach(doc -> {
System.out.println(doc.getString("name") + " has " +
doc.getList("orders", Document.class).size() + " orders");
});
}
事务管理
MongoDB 4.0+ 支持多文档ACID事务。
1. 配置事务支持
@Configuration
public class MongoConfig {
@Bean
public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}
2. 编程式事务
@Service
public class UserService {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private MongoTransactionManager transactionManager;
public void transferPoints(String fromUserId, String toUserId, int points) {
// 获取事务定义
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setReadOnly(false);
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
// 开启事务
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 扣减源用户积分
Query fromQuery = new Query(Criteria.where("id").is(fromUserId));
Update fromUpdate = new Update().inc("points", -points);
mongoTemplate.updateFirst(fromQuery, fromUpdate, User.class);
// 增加目标用户积分
Query toQuery = new Query(Criteria.where("id").is(toUserId));
Update toUpdate = new Update().inc("points", points);
mongoTemplate.updateFirst(toQuery, toUpdate, User.class);
// 提交事务
transactionManager.commit(status);
} catch (Exception e) {
// 回滚事务
transactionManager.rollback(status);
throw new RuntimeException("Transfer failed", e);
}
}
}
3. 声明式事务(@Transactional)
@Service
public class OrderService {
@Autowired
private MongoTemplate mongoTemplate;
@Transactional
public void placeOrder(Order order) {
// 1. 保存订单
mongoTemplate.insert(order);
// 2. 更新用户订单计数
Query query = new Query(Criteria.where("id").is(order.getUserId()));
Update update = new Update().inc("orderCount", 1);
mongoTemplate.updateFirst(query, update, User.class);
// 3. 更新库存
order.getItems().forEach(item -> {
Query stockQuery = new Query(
Criteria.where("productId").is(item.getProductId())
);
Update stockUpdate = new Update().inc("quantity", -item.getQuantity());
mongoTemplate.updateFirst(stockQuery, stockUpdate, Inventory.class);
});
}
}
事务配置注意事项:
- MongoDB事务需要复制集或分片集群
- 事务默认超时时间为60秒,可通过
@Transactional(timeout=30)
调整 - 跨多个集合的事务操作需要相同的会话
性能优化
1. 索引优化
// 1. 创建索引
@SpringBootTest
public class IndexTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void createIndexes() {
// 单字段索引
mongoTemplate.indexOps(User.class).ensureIndex(
new Index().on("username", Sort.Direction.ASC).unique()
);
// 复合索引
mongoTemplate.indexOps(User.class).ensureIndex(
new Index().on("age", Sort.Direction.ASC)
.on("createTime", Sort.Direction.DESC)
.named("age_createTime_idx")
);
// 文本索引
mongoTemplate.indexOps(BlogPost.class).ensureIndex(
new Index().on("title", Sort.Direction.ASC)
.on("content", Sort.Direction.ASC)
.named("text_idx")
);
}
// 2. 查看索引
@Test
public void listIndexes() {
IndexOperations indexOps = mongoTemplate.indexOps(User.class);
indexOps.getIndexInfo().forEach(index -> {
System.out.println("Index: " + index.getName());
System.out.println("Keys: " + index.getIndexKeys());
System.out.println("Options: " + index.getIndexOptions());
});
}
}
索引设计原则:
- ESR规则(Equality, Sort, Range)设计复合索引
- 查询覆盖率尽量高
- 写频繁的集合避免过多索引
- 定期监控和优化索引
2. 读写分离
配置副本集读写分离:
spring:
data:
mongodb:
uri: mongodb://user:pass@primary:27017,secondary1:27017,secondary2:27017/db?replicaSet=rs0&readPreference=secondaryPreferred
读偏好(Read Preference)选项:
选项 | 说明 | 适用场景 |
---|---|---|
primary | 只从主节点读(默认) | 强一致性要求 |
primaryPreferred | 优先主节点,不可用时从从节点读 | 多数情况可用 |
secondary | 只从从节点读 | 报表查询等非实时需求 |
secondaryPreferred | 优先从节点,不可用时从主节点读 | 读写分离场景 |
nearest | 从网络延迟最低的节点读 | 地理分布式应用 |
3. 批量操作优化
public class BulkOperationsTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void testBulkOps() {
// 1. 有序批量操作(顺序执行,出错即停止)
BulkOperations bulkOps = mongoTemplate.bulkOps(BulkMode.ORDERED, User.class);
// 添加多个操作
for (int i = 0; i < 100; i++) {
Query query = new Query(Criteria.where("username").is("user" + i));
Update update = new Update().set("lastLogin", new Date());
bulkOps.upsert(query, update);
}
// 执行批量操作
BulkWriteResult result = bulkOps.execute();
System.out.println("Inserted: " + result.getInsertedCount());
System.out.println("Updated: " + result.getModifiedCount());
// 2. 无序批量操作(并行执行,效率更高)
BulkOperations unorderedBulk = mongoTemplate.bulkOps(BulkMode.UNORDERED, User.class);
// ...添加操作
}
}
批量操作建议:
- 大批量操作使用UNORDERED模式
- 合理设置批量大小(通常100-1000个操作一批)
- 考虑在低峰期执行大批量操作
安全配置
1. 认证与授权
MongoDB用户角色:
角色 | 权限 |
---|---|
read | 只读权限 |
readWrite | 读写权限 |
dbAdmin | 数据库管理权限 |
userAdmin | 用户管理权限 |
clusterAdmin | 集群管理权限(admin数据库) |
创建用户示例:
// 在MongoDB shell中执行
use blog_db
db.createUser({
user: "blog_user",
pwd: "securepwd",
roles: [
{ role: "readWrite", db: "blog_db" },
{ role: "read", db: "reporting" }
]
})
2. 加密配置
spring:
data:
mongodb:
uri: mongodb://user:pass@host:27017/db?ssl=true&tlsInsecure=true
auto-index-creation: false # 生产环境建议关闭
安全建议:
- 启用TLS/SSL加密传输
- 使用强密码并定期更换
- 遵循最小权限原则分配角色
- 启用审计日志(企业版)
- 配置网络访问控制
3. 字段级加密
@Document
@Data
public class Patient {
@Id
private String id;
private String name;
@Encrypted // 需要配置加密密钥
private String ssn; // 社会安全号
@Field(targetType = FieldType.BINARY)
private byte[] medicalReport; // 加密存储的二进制数据
}
最佳实践与常见问题
1. 设计模式建议
嵌入 vs 引用 选择指南:
考虑因素 | 嵌入文档 | 引用文档 |
---|---|---|
数据关系 | 一对一或一对少 | 一对多或多对多 |
数据大小 | 小文档 | 大文档 |
变化频率 | 不频繁变化 | 频繁变化 |
一致性要求 | 强一致性 | 最终一致性 |
读取模式 | 需要一起读取 | 单独读取 |
示例场景:
- 用户地址适合嵌入(一对一,变化不频繁)
- 博客评论可嵌入(一对少,通常一起查询)
- 订单商品适合引用(可能变化,需要独立管理)
2. 常见问题解决方案
问题1:查询性能慢
- 检查是否使用了合适的索引(explain()分析)
- 避免全表扫描和大结果集
- 考虑分页或游标查询
问题2:写入延迟高
- 检查写入关注级别(write concern)
- 考虑批量写入代替单条写入
- 评估是否需要索引优化
问题3:连接池耗尽
- 调整连接池大小
- 确保正确关闭连接
- 使用连接池监控
// 获取连接池统计信息
@Autowired
private MongoClient mongoClient;
public void printPoolStats() {
MongoClientSettings settings = mongoClient.getSettings();
ConnectionPoolSettings poolSettings = settings.getConnectionPoolSettings();
System.out.println("Max connections: " + poolSettings.getMaxSize());
System.out.println("Min connections: " + poolSettings.getMinSize());
System.out.println("Wait queue size: " + poolSettings.getMaxWaitQueueSize());
// 更详细的统计需要特定驱动版本支持
}
3. 监控与维护
关键监控指标:
指标 | 说明 | 健康值 |
---|---|---|
查询执行时间 | 查询耗时 | <100ms |
扫描/返回比 | 扫描文档数与返回数比 | 接近1:1 |
连接数 | 当前活跃连接 | <75%最大连接数 |
队列长度 | 等待操作的请求数 | 低 |
内存使用 | 工作集大小 | 小于物理内存 |
Spring Boot Actuator集成:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置application.yml:
management:
endpoints:
web:
exposure:
include: health,metrics,mongodb
endpoint:
health:
show-details: always
访问/actuator/mongodb
获取MongoDB健康状态。
总结
本文全面介绍了Spring Boot与MongoDB的整合,从基础配置到高级特性,涵盖了:
- 基础操作:CRUD、查询构建、Repository模式
- 高级特性:聚合框架、事务管理、地理查询
- 性能优化:索引设计、批量操作、读写分离
- 安全实践:认证授权、加密传输
- 运维知识:监控、连接池管理、常见问题
MongoDB与Spring Boot的组合为现代应用开发提供了灵活、可扩展的数据持久化方案。根据应用特点合理选择文档设计模式,充分利用MongoDB的优势,同时注意其与传统关系型数据库的差异,才能构建高性能的应用程序。
附录
常用命令对照表
MongoDB操作 | SQL等效 | MongoTemplate方法 |
---|---|---|
db.collection.find() | SELECT | find()/query() |
db.collection.insert() | INSERT | insert()/save() |
db.collection.update() | UPDATE | updateFirst()/updateMulti() |
db.collection.remove() | DELETE | remove() |
db.collection.aggregate() | GROUP BY | aggregate() |
db.collection.createIndex() | CREATE INDEX | indexOps().ensureIndex() |
版本兼容性
Spring Boot版本 | Spring Data MongoDB版本 | MongoDB驱动版本 | MongoDB服务器版本 |
---|---|---|---|
2.4.x | 3.1.x | 4.1.x | 4.2-4.4 |
2.5.x | 3.2.x | 4.2.x | 4.2-5.0 |
2.6.x | 3.3.x | 4.4.x | 4.4-5.0 |
2.7.x | 3.4.x | 4.6.x | 5.0+ |
3.0.x | 4.0.x | 4.8.x | 5.0+ |
收藏与否,我不在乎(才怪)。
喜欢的点个关注,想了解更多的可以关注微信公众号 “Eric的技术杂货库” ,提供更多的干货以及资料下载保存!