10分钟上手MongoDB开发:用MyBatis-Plus的方式优雅操作文档数据库
【免费下载链接】mongo-plus 🔥🔥🔥使用MyBatisPlus的方式,优雅的操作MongoDB 项目地址: https://gitcode.com/aizuda/mongo-plus
引言:MongoDB开发的3大痛点与解决方案
你是否还在为MongoDB的Java驱动API冗长复杂而烦恼?是否在关系型数据库与文档数据库的思维切换中感到混乱?是否因为缺少统一的CRUD接口而导致代码风格不统一?
mongo-plus(MongoDB增强工具包)正是为解决这些问题而生。它借鉴了MyBatis-Plus的设计思想,提供了一套简洁、高效、类型安全的API,让开发者能够用熟悉的方式操作MongoDB。本文将带你从零开始,快速掌握mongo-plus的核心功能与最佳实践。
读完本文后,你将能够:
- 使用mongo-plus快速实现MongoDB的CRUD操作
- 掌握条件构造器的高级用法,构建复杂查询
- 理解mongo-plus的核心架构与扩展点
- 解决MongoDB开发中的常见痛点问题
快速入门:10分钟搭建mongo-plus开发环境
环境准备
首先,我们需要准备基础的开发环境。mongo-plus支持JDK 8+、MongoDB 4.0+,并提供了Spring Boot Starter,方便快速集成。
1. 添加依赖
在你的Maven项目中,添加以下依赖:
<!-- mongo-plus核心依赖 -->
<dependency>
<groupId>com.mongoplus</groupId>
<artifactId>mongo-plus-boot-starter</artifactId>
<version>最新版本</version>
</dependency>
<!-- MongoDB Java驱动 -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.6.0</version>
</dependency>
2. 配置MongoDB连接
在application.properties中添加MongoDB连接配置:
# MongoDB连接配置
spring.data.mongodb.uri=mongodb://localhost:27017/test
# 连接池配置
spring.data.mongodb.connection-pool.max-size=10
spring.data.mongodb.connection-pool.min-size=2
# 超时配置
spring.data.mongodb.socket-timeout=30000
spring.data.mongodb.connect-timeout=10000
3. 创建实体类
定义一个User实体类,使用mongo-plus的注解进行映射:
@Data
@Accessors(chain = true)
@Collection("user") // 指定集合名称
public class User {
@ID(type = IdTypeEnum.AUTO) // 自动生成ID
private String id;
@Field("username") // 映射集合中的字段名
private String username;
@Field("age")
private Integer age;
@Field("email")
private String email;
@Field("create_time")
private LocalDateTime createTime;
@Field("update_time")
private LocalDateTime updateTime;
@Field("tags")
private List<String> tags;
@Field("address")
private Address address; // 嵌入式文档
@Field("is_deleted")
@LogicDelete // 逻辑删除注解
private Boolean deleted = false;
}
@Data
public class Address {
private String province;
private String city;
private String detail;
}
4. 创建Mapper接口
定义UserMapper接口,继承BaseMapper:
public interface UserMapper extends BaseMapper<User> {
// 继承BaseMapper后,自动拥有CRUD方法
}
5. 注入并使用Mapper
在Spring Boot应用中,直接注入UserMapper即可使用:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 使用mongo-plus进行CRUD操作
public void createUser() {
User user = new User()
.setUsername("张三")
.setAge(25)
.setEmail("zhangsan@example.com")
.setCreateTime(LocalDateTime.now())
.setUpdateTime(LocalDateTime.now())
.setTags(Arrays.asList("java", "mongodb", "mongo-plus"))
.setAddress(new Address().setProvince("广东").setCity("深圳").setDetail("科技园路1号"));
// 插入数据
boolean success = userMapper.save(user);
System.out.println("插入结果: " + success + ", 生成的ID: " + user.getId());
}
}
核心功能详解:从CRUD到高级查询
1. 基础CRUD操作
mongo-plus的BaseMapper接口提供了丰富的CRUD方法,覆盖了大部分日常操作需求。
插入操作
// 插入单条数据
User user = new User();
// ... 设置属性
boolean success = userMapper.save(user);
// 批量插入
List<User> userList = new ArrayList<>();
// ... 添加用户
boolean batchSuccess = userMapper.saveBatch(userList);
// 批量插入(带选项)
InsertManyOptions options = new InsertManyOptions().ordered(false);
boolean batchWithOptions = userMapper.saveBatch(userList, options);
查询操作
// 根据ID查询
User user = userMapper.getById("60d21b4667d0d8992e610c85");
// 条件查询
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.eq("age", 25)
.like("username", "张")
.orderByDesc("create_time");
List<User> userList = userMapper.list(queryWrapper);
// 分页查询
PageParam pageParam = new PageParam(1, 10); // 第1页,每页10条
PageResult<User> pageResult = userMapper.page(pageParam, queryWrapper);
System.out.println("总记录数: " + pageResult.getTotal());
System.out.println("当前页数据: " + pageResult.getRecords());
更新操作
// 根据ID更新
User user = new User();
user.setId("60d21b4667d0d8992e610c85");
user.setAge(26);
boolean updateSuccess = userMapper.updateById(user);
// 条件更新
UpdateChainWrapper<User, ?> updateWrapper = new UpdateChainWrapper<>();
updateWrapper.set("age", 26)
.set("update_time", LocalDateTime.now());
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.eq("username", "张三");
boolean conditionUpdateSuccess = userMapper.update(updateWrapper, queryWrapper);
删除操作
// 根据ID删除
boolean deleteSuccess = userMapper.removeById("60d21b4667d0d8992e610c85");
// 条件删除
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.eq("age", 25);
boolean conditionDeleteSuccess = userMapper.remove(queryWrapper);
// 批量删除
List<String> ids = Arrays.asList("id1", "id2", "id3");
boolean batchDeleteSuccess = userMapper.removeBatchByIds(ids);
2. 高级条件构造器
mongo-plus的条件构造器提供了丰富的查询条件方法,支持链式调用,让查询构建更加直观和灵活。
比较操作符
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.eq("username", "张三") // 等于
.ne("status", 0) // 不等于
.gt("age", 18) // 大于
.ge("score", 60) // 大于等于
.lt("height", 180) // 小于
.lte("weight", 75) // 小于等于
.between("create_time", startDate, endDate) // 介于之间
.notBetween("update_time", startDate, endDate) // 不介于之间
.in("tags", Arrays.asList("java", "mongodb")) // 在列表中
.notIn("role", Arrays.asList("admin", "super_admin")); // 不在列表中
逻辑操作符
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.and(qw -> qw.eq("age", 25).or().eq("age", 30)) // AND 条件组
.or(qw -> qw.like("username", "张").like("username", "李")) // OR 条件组
.not(qw -> qw.eq("status", 1)) // NOT 条件组
.exists("email") // 字段存在
.notExists("phone"); // 字段不存在
模糊查询
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.like("username", "张") // 包含"张"
.likeLeft("email", "example.com") // 以"example.com"结尾
.likeRight("address.city", "深") // 以"深"开头
.regex("username", "^[A-Za-z]+$"); // 正则表达式
数组操作
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.all("tags", Arrays.asList("java", "mongodb")) // 数组包含所有元素
.elemMatch("addresses", qw -> qw.eq("city", "深圳")) // 数组元素匹配
.size("tags", 3); // 数组长度为3
排序与投影
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.orderByAsc("age") // 按年龄升序
.orderByDesc("create_time") // 按创建时间降序
.projectDisplay("username", "age", "email") // 只返回指定字段
.projectNone("password"); // 不返回密码字段
3. 聚合查询
mongo-plus提供了强大的聚合查询支持,可以轻松实现复杂的数据统计分析需求。
// 构建聚合查询
Aggregate<User> aggregate = new Aggregate<>();
// 匹配条件
aggregate.match(new QueryChainWrapper<User>().gt("age", 18));
// 分组统计
aggregate.group("address.province")
.count("count")
.avg("age", "avgAge")
.max("age", "maxAge")
.min("age", "minAge");
// 排序
aggregate.sort(new QueryChainWrapper<>().orderByDesc("count"));
// 限制结果数量
aggregate.limit(10);
// 执行聚合查询
List<Map<String, Object>> result = userMapper.aggregateList(aggregate);
// 结果处理
for (Map<String, Object> item : result) {
System.out.println("省份: " + item.get("_id"));
System.out.println("用户数量: " + item.get("count"));
System.out.println("平均年龄: " + item.get("avgAge"));
System.out.println("最大年龄: " + item.get("maxAge"));
System.out.println("最小年龄: " + item.get("minAge"));
}
高级特性:提升开发效率的实用功能
1. 逻辑删除
mongo-plus支持逻辑删除功能,通过注解@LogicDelete实现:
public class User {
// ... 其他字段
@LogicDelete // 默认字段名为is_deleted,值为true表示删除
private Boolean deleted;
// 也可以自定义字段名和值
// @LogicDelete(value = "deleted", delval = "1", undelval = "0")
// private String deleted;
}
启用逻辑删除后,所有查询和删除操作都会自动加上逻辑删除条件,无需手动处理:
// 查询操作会自动过滤已删除数据
List<User> userList = userMapper.list(new QueryChainWrapper<>());
// 删除操作会变为更新操作,设置deleted=true
boolean success = userMapper.removeById("id");
// 等价于 update user set deleted=true where id='id'
2. 自动填充
mongo-plus支持字段自动填充功能,通过@TableField注解的fill属性指定填充策略:
public class User {
// ... 其他字段
@TableField(fill = FieldFill.INSERT) // 插入时填充
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时填充
private LocalDateTime updateTime;
}
实现MetaObjectHandler接口自定义填充规则:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 设置创建时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
// 设置更新时间
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 设置更新时间
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
3. 乐观锁
mongo-plus支持乐观锁功能,通过@Version注解实现:
public class Product {
@ID
private String id;
private String name;
private Integer stock;
@Version // 乐观锁版本字段
private Integer version;
}
使用乐观锁后,更新操作会自动检查版本号:
// 查询商品
Product product = productMapper.getById("id");
// 修改库存
product.setStock(product.getStock() - 1);
// 更新操作会自动带上版本条件,并更新版本号
boolean success = productMapper.updateById(product);
// 等价于 update product set stock=?, version=version+1 where id=? and version=?
4. 多数据源
mongo-plus支持多数据源配置,可以轻松切换不同的MongoDB实例:
// 配置多数据源
@Configuration
public class MongoPlusConfig {
@Bean
@Primary
public MongoClient primaryMongoClient() {
return MongoClients.create("mongodb://localhost:27017/test");
}
@Bean
public MongoClient secondaryMongoClient() {
return MongoClients.create("mongodb://localhost:27018/test");
}
@Bean
public MongoPlusClient mongoPlusClient(MongoClient primaryMongoClient) {
return new MongoPlusClient(primaryMongoClient);
}
@Bean
public DataSourceManager dataSourceManager(MongoPlusClient mongoPlusClient,
@Qualifier("secondaryMongoClient") MongoClient secondaryMongoClient) {
DataSourceManager manager = new DataSourceManager();
manager.setDefaultDataSource(mongoPlusClient);
manager.addDataSource("secondary", secondaryMongoClient);
return manager;
}
}
在Mapper或方法上指定数据源:
// 在Mapper上指定默认数据源
@DataSource("secondary")
public interface OrderMapper extends BaseMapper<Order> {
// 在方法上指定数据源(优先级高于类上的注解)
@DataSource("primary")
List<Order> selectSpecialOrders();
}
架构解析:mongo-plus的设计思想
1. 核心架构
mongo-plus的核心架构采用了分层设计,主要包含以下几个部分:
2. 执行流程
mongo-plus的CRUD操作执行流程如下:
3. 扩展点
mongo-plus提供了丰富的扩展点,可以根据需求自定义功能:
- 拦截器(Interceptor):拦截CRUD操作,添加自定义逻辑
- 类型处理器(TypeHandler):自定义字段的序列化和反序列化
- 元对象处理器(MetaObjectHandler):处理字段自动填充
- ID生成器(IdentifierGenerator):自定义ID生成策略
- 数据源处理器(DataSourceHandler):处理多数据源切换
最佳实践与性能优化
1. 索引优化
合理的索引设计是提升MongoDB查询性能的关键。mongo-plus支持通过注解定义索引:
@Data
@Collection("user")
@Indexes({
@Index(fields = "username", unique = true), // 唯一索引
@Index(fields = "age", direction = IndexDirection.ASC), // 普通索引
@Index(fields = {"address.province", "address.city"}) // 复合索引
})
public class User {
// ... 字段定义
}
也可以通过代码动态创建索引:
// 创建索引
Index index = new Index();
index.on("username", IndexDirection.ASC);
index.unique(true);
userMapper.createIndex(index);
// 查看索引
List<Document> indexes = userMapper.getIndexes();
2. 查询优化
- 只返回需要的字段:使用投影功能减少数据传输量
- 使用批量操作:减少网络往返次数
- 合理使用索引:避免全表扫描
- 分页查询优化:使用游标分页代替offset分页
// 只返回需要的字段
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.projectDisplay("username", "age", "email");
List<User> userList = userMapper.list(queryWrapper);
// 批量操作
List<User> userList = new ArrayList<>();
// ... 添加用户
boolean success = userMapper.saveBatch(userList);
// 游标分页
QueryChainWrapper<User, ?> queryWrapper = new QueryChainWrapper<>();
queryWrapper.orderByAsc("_id").limit(10);
List<User> firstPage = userMapper.list(queryWrapper);
// 下一页
if (!firstPage.isEmpty()) {
String lastId = firstPage.get(firstPage.size() - 1).getId();
QueryChainWrapper<User, ?> nextQueryWrapper = new QueryChainWrapper<>();
nextQueryWrapper.gt("_id", lastId).orderByAsc("_id").limit(10);
List<User> nextPage = userMapper.list(nextQueryWrapper);
}
3. 避免常见陷阱
- 不要过度使用嵌套文档:过深的嵌套会影响查询和更新性能
- 注意数组操作的性能:对大数组进行操作可能导致性能问题
- 避免在查询条件中使用函数:会导致索引失效
- 注意写入性能:批量写入比单条写入更高效
- 合理设置读写关注级别:根据业务需求平衡性能和一致性
总结与展望
mongo-plus为Java开发者提供了一套优雅的MongoDB操作方案,它借鉴了MyBatis-Plus的设计思想,降低了MongoDB的学习和使用成本。通过本文的介绍,我们了解了mongo-plus的核心功能、使用方法和最佳实践。
mongo-plus的主要优势包括:
- 简洁易用的API,降低学习成本
- 强大的条件构造器,支持复杂查询
- 丰富的注解支持,减少重复代码
- 完善的扩展机制,方便自定义功能
- 良好的性能表现,适合生产环境
未来,mongo-plus将继续完善功能,计划支持更多高级特性,如分布式事务、更丰富的聚合操作、与Spring Data的深度集成等。
如果你正在使用MongoDB进行Java开发,不妨尝试一下mongo-plus,相信它会给你带来更愉悦的开发体验。
附录:常用API速查表
BaseMapper接口常用方法
| 方法名 | 描述 | 示例 |
|---|---|---|
| save(T entity) | 插入单条数据 | userMapper.save(user) |
| saveBatch(Collection entityList) | 批量插入 | userMapper.saveBatch(userList) |
| getById(Serializable id) | 根据ID查询 | userMapper.getById("id") |
| list(QueryChainWrapper<T, ?> queryWrapper) | 条件查询列表 | userMapper.list(queryWrapper) |
| page(PageParam pageParam, QueryChainWrapper<T, ?> queryWrapper) | 分页查询 | userMapper.page(pageParam, queryWrapper) |
| updateById(T entity) | 根据ID更新 | userMapper.updateById(user) |
| update(T entity, QueryChainWrapper<T, ?> queryWrapper) | 条件更新 | userMapper.update(user, queryWrapper) |
| removeById(Serializable id) | 根据ID删除 | userMapper.removeById("id") |
| remove(QueryChainWrapper<T, ?> queryWrapper) | 条件删除 | userMapper.remove(queryWrapper) |
| aggregateList(Aggregate aggregate) | 聚合查询 | userMapper.aggregateList(aggregate) |
QueryChainWrapper常用方法
| 方法名 | 描述 | 示例 |
|---|---|---|
| eq(String column, Object value) | 等于 | eq("age", 25) |
| ne(String column, Object value) | 不等于 | ne("status", 0) |
| gt(String column, Object value) | 大于 | gt("age", 18) |
| ge(String column, Object value) | 大于等于 | ge("score", 60) |
| lt(String column, Object value) | 小于 | lt("height", 180) |
| lte(String column, Object value) | 小于等于 | lte("weight", 75) |
| like(String column, Object value) | 模糊查询 | like("username", "张") |
| in(String column, Collection<?> values) | 包含 | in("tags", Arrays.asList("java", "mongodb")) |
| and(QueryChainWrapper queryWrapper) | AND条件 | and(qw -> qw.eq("a", 1).eq("b", 2)) |
| or(QueryChainWrapper queryWrapper) | OR条件 | or(qw -> qw.eq("a", 1).eq("b", 2)) |
| orderByAsc(String column) | 升序排序 | orderByAsc("age") |
| orderByDesc(String column) | 降序排序 | orderByDesc("create_time") |
| projectDisplay(String... columns) | 只返回指定字段 | projectDisplay("username", "age") |
UpdateChainWrapper常用方法
| 方法名 | 描述 | 示例 |
|---|---|---|
| set(String column, Object value) | 设置字段值 | set("age", 26) |
| inc(String column, Number value) | 自增 | inc("score", 10) |
| dec(String column, Number value) | 自减 | dec("stock", 1) |
| setNull(String column) | 设置字段为null | setNull("phone") |
| push(String column, Object value) | 数组添加元素 | push("tags", "mongo-plus") |
| pull(String column, Object value) | 数组删除元素 | pull("tags", "old") |
| rename(String oldColumn, String newColumn) | 重命名字段 | rename("oldName", "newName") |
| currentDate(String column) | 设置为当前时间 | currentDate("update_time") |
【免费下载链接】mongo-plus 🔥🔥🔥使用MyBatisPlus的方式,优雅的操作MongoDB 项目地址: https://gitcode.com/aizuda/mongo-plus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



