首页 开发教程 Spring Boot MongoDB 使用技巧

Spring Boot MongoDB 使用技巧

开发教程 2025年12月4日
160 浏览

Spring Boot MongoDB 使用技巧

1. 基础配置

1.1 依赖配置


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

1.2 连接配置

# application.yml 配置示例
spring:
  data:
    mongodb:
      uri: mongodb://username:password@host:port/database?authSource=admin
      # 或者使用分开的配置
      # host: localhost
      # port: 27017
      # database: testdb
      # username: admin
      # password: password
      # authentication-database: admin

1.3 多数据源配置

@Configuration
public class MultipleMongoConfig {

    @Bean(name = \"mongoTemplate1\")
    @Primary
    public MongoTemplate mongoTemplate1(MongoDatabaseFactory factory1) {
        return new MongoTemplate(factory1);
    }

    @Bean(name = \"mongoTemplate2\")
    public MongoTemplate mongoTemplate2(@Qualifier(\"mongoDbFactory2\") MongoDatabaseFactory factory2) {
        return new MongoTemplate(factory2);
    }

    // 配置多个MongoDatabaseFactory
}

2. 实体映射技巧

2.1 基础映射注解

@Document(collection = \"users\")  // 指定集合名
public class User {
    @Id  // 主键
    private String id;
    
    @Field(\"user_name\")  // 自定义字段名
    private String username;
    
    @Indexed(unique = true)  // 索引配置
    private String email;
    
    @Transient  // 不持久化到数据库
    private String tempField;
    
    // getters and setters
}

2.2 复杂对象映射

@Document
public class Order {
    @Id
    private String id;
    
    private User user;  // 嵌入文档
    
    private List items;  // 数组/列表
    
    @DBRef  // 引用其他集合的文档
    private Customer customer;
    
    // getters and setters
}

2.3 时间处理

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime createdAt;

// 自动填充时间
@PrePersist
public void prePersist() {
    createdAt = LocalDateTime.now();
}

3. 数据访问层设计

3.1 Repository接口方式

// 基础Repository
public interface UserRepository extends MongoRepository {
    // 自动生成查询方法
    Optional findByUsername(String username);
    List findByAgeGreaterThan(int age);
    
    // 自定义查询
    @Query(\"{ \'email\' : ?0, \'status\' : ?1 }\")
    List findByEmailAndStatus(String email, String status);
}

3.2 MongoTemplate方式

@Service
public class UserService {
    
    @Autowired
    private MongoTemplate mongoTemplate;
    
    public User findUserByUsername(String username) {
        Query query = new Query(Criteria.where(\"username\").is(username));
        return mongoTemplate.findOne(query, User.class);
    }
    
    public void saveUser(User user) {
        mongoTemplate.save(user);
    }
}

4. 高级查询技巧

4.1 复杂条件查询

// 使用Criteria构建复杂查询
Criteria criteria = new Criteria();
criteria.and(\"age\").gt(18).lte(60);
criteria.and(\"status\").is(\"active\");
criteria.orOperator(
    Criteria.where(\"role\").is(\"admin\"),
    Criteria.where(\"permissions\").in(\"WRITE\", \"DELETE\")
);
Query query = Query.query(criteria);
List users = mongoTemplate.find(query, User.class);

4.2 聚合查询

Aggregation aggregation = Aggregation.newAggregation(
    Aggregation.match(Criteria.where(\"status\").is(\"active\")),
    Aggregation.group(\"department\").count().as(\"employeeCount\"),
    Aggregation.sort(Sort.Direction.DESC, \"employeeCount\")
);

AggregationResults results = mongoTemplate.aggregate(
    aggregation, \"employees\", DepartmentStats.class);

4.3 分页查询

Pageable pageable = PageRequest.of(0, 10, Sort.by(\"createdAt\").descending());
Query query = new Query().with(pageable);
long count = mongoTemplate.count(query, User.class);
List users = mongoTemplate.find(query, User.class);
Page userPage = new PageImpl(users, pageable, count);

5. 索引优化

5.1 索引注解配置

@Document
@CompoundIndex(name = \"idx_name_age\", def = \"{ \'name\': 1, \'age\': -1 }\")
public class User {
    @Indexed(unique = true, sparse = true)  // 唯一索引,稀疏索引
    private String email;
    
    @Indexed(expireAfterSeconds = 3600)  // TTL索引,1小时后过期
    private Date lastLoginTime;
}

5.2 运行时索引管理

// 创建索引
mongoTemplate.indexOps(User.class).ensureIndex(
    new Index().on(\"username\", Direction.ASC).unique()
);

// 删除索引
mongoTemplate.indexOps(User.class).dropIndex(\"idx_name_age\");

// 查看所有索引
List indexes = mongoTemplate.indexOps(User.class).getIndexInfo();

6. 事务支持

6.1 启用事务

@Configuration
@EnableMongoRepositories
public class MongoConfig extends AbstractMongoClientConfiguration {
    
    @Bean
    @Override
    public MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }
}

6.2 使用事务

@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Transactional  // Spring事务注解
    public void createOrder(Order order) {
        // 保存订单
        orderRepository.save(order);
        
        // 更新库存
        inventoryService.reduceInventory(order.getItems());
    }
}

7. 性能优化技巧

7.1 字段投影

// 只返回需要的字段
Query query = new Query(Criteria.where(\"status\").is(\"active\"));
query.fields().include(\"username\").include(\"email\").exclude(\"password\");
List users = mongoTemplate.find(query, User.class);

7.2 批量操作

// 批量插入
List users = new ArrayList();
// 添加用户...
mongoTemplate.insert(users, User.class);

// 批量更新
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, User.class);
for (User user : usersToUpdate) {
    Update update = new Update().set(\"status\", user.getStatus());
    operations.updateOne(Query.query(Criteria.where(\"_id\").is(user.getId())), update);
}
operations.execute();

7.3 缓存查询结果

@Service
public class CacheUserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Cacheable(value = \"users\", key = \"#username\")
    public User findByUsername(String username) {
        return userRepository.findByUsername(username).orElse(null);
    }
}

8. 错误处理与日志

8.1 异常处理

@ControllerAdvice
public class MongoExceptionHandler {
    
    @ExceptionHandler(DuplicateKeyException.class)
    public ResponseEntity handleDuplicateKey(DuplicateKeyException ex) {
        ErrorResponse error = new ErrorResponse(\"Duplicate key error\", ex.getMessage());
        return new ResponseEntity(error, HttpStatus.CONFLICT);
    }
    
    @ExceptionHandler(MongoException.class)
    public ResponseEntity handleMongoException(MongoException ex) {
        ErrorResponse error = new ErrorResponse(\"MongoDB error\", ex.getMessage());
        return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

8.2 慢查询日志配置

logging:
  level:
    org.springframework.data.mongodb.core.MongoTemplate: DEBUG  # 开启MongoTemplate日志

9. 测试技巧

9.1 集成测试

@SpringBootTest
@DataMongoTest  // 只加载MongoDB相关配置
public class UserRepositoryTest {
    
    @Autowired
    private UserRepository userRepository;
    
    @MockBean  // 模拟其他依赖
    private EmailService emailService;
    
    @Test
    public void testFindByUsername() {
        // 测试代码
    }
}

9.2 使用嵌入式MongoDB

<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <scope>test</scope>
</dependency>

10. 最佳实践总结

  1. 合理设计文档结构:优先使用嵌入文档,避免过度使用DBRef
  2. 索引策略:为常用查询字段添加索引,但不要过度索引
  3. 事务使用:仅在必要时使用事务,因为会影响性能
  4. 连接池配置:根据应用规模调整连接池参数
  5. 分页查询:避免深度分页,考虑使用游标或时间戳分页
  6. 监控与调优:使用MongoDB Compass等工具监控查询性能
  7. 安全配置:生产环境启用认证、TLS加密
  8. 备份策略:定期备份数据,配置适当的复制集

这些技巧涵盖了Spring Boot与MongoDB集成的各个方面,从基础配置到高级用法和性能优化,希望对你有所帮助!

发表评论
暂无评论

还没有评论呢,快来抢沙发~

客服

点击联系客服 点击联系客服

在线时间:09:00-18:00

关注微信公众号

关注微信公众号
客服电话

400-888-8888

客服邮箱 122325244@qq.com

手机

扫描二维码

手机访问本站

扫描二维码
搜索