专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

SpringBoot整合MongoDB教程:配置、CRUD、事务与聚合全流程详解

什么是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  连接池最小连接数  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  平均值  age" 
$min  最小值  price" 
$max  最大值  score" 
$push  将值加入数组  name" 
$addToSet  将唯一值加入数组  category" 
$first  获取第一个文档值  timestamp" 
$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);
        });
    }
}

事务配置注意事项:

1、 MongoDB事务需要复制集或分片集群
2、 事务默认超时时间为60秒,可通过 @Transactional(timeout=30) 调整
3、 跨多个集合的事务操作需要相同的会话

性能优化

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());
        });
    }
}

索引设计原则:

1、 ESR规则(Equality, Sort, Range)设计复合索引
2、 查询覆盖率尽量高
3、 写频繁的集合避免过多索引
4、 定期监控和优化索引

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);
        // ...添加操作
    }
}

批量操作建议:

1、 大批量操作使用UNORDERED模式
2、 合理设置批量大小(通常100-1000个操作一批)
3、 考虑在低峰期执行大批量操作

安全配置

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  # 生产环境建议关闭

安全建议:

1、 启用TLS/SSL加密传输
2、 使用强密码并定期更换
3、 遵循最小权限原则分配角色
4、 启用审计日志(企业版)
5、 配置网络访问控制

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的整合,从基础配置到高级特性,涵盖了:

1、 基础操作 :CRUD、查询构建、Repository模式
2、 高级特性 :聚合框架、事务管理、地理查询
3、 性能优化 :索引设计、批量操作、读写分离
4、 安全实践 :认证授权、加密传输
5、 运维知识 :监控、连接池管理、常见问题

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+ 
未经允许不得转载:搜云库 » SpringBoot整合MongoDB教程:配置、CRUD、事务与聚合全流程详解

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们