作为常年奋战在业务代码一线的老码农,我深知传统 MyBatis 开发中那些烦人的重复劳动。每次新开一个模块,Controller、Service、Mapper、XML 四件套轮番上阵,尤其是那些基础的增删改查,代码写得手软。直到团队全面拥抱 MyBatis-Plus (简称 MP),才真正体会到了什么叫"解放生产力"。今天就跟大伙儿唠唠,MP 的 CRUD 增强到底强在哪,怎么用才最香。
一、传统 CRUD 的问题
想象一下这个场景:你要开发一个简单的用户管理模块。
- 在
UserMapper.java
里定义接口:insert(User user)
,selectById(Long id)
,updateById(User user)
,deleteById(Long id)
... - 在
UserMapper.xml
里吭哧吭哧写对应的<insert>
,<select>
,<update>
,<delete>
SQL 语句。 - Service 层调用 Mapper,Controller 调用 Service... 一堆模板代码。
- 重复劳动: 每个实体都要写一套几乎相同的 CRUD 操作。
- 易错: SQL 手写,字段名容易拼错。
- 维护难: 字段增减,所有相关 SQL 都得改。
- 效率低: 大量时间花在基础操作上,而非核心业务。
二、MP:CRUD的增强
MP 的 CRUD 增强,核心在于帮我们进行一些自动化的基础操作,让我们将精力主要集中在逻辑层。主要体现在四个方面吧!
1:BaseMapper - 开箱即用的 CRUD 接口
核心思想: MP 为你的 Mapper 接口提供了一个功能强大的"爹" - BaseMapper<T>
。你的 Mapper 只需要继承它,就自动拥有了数十个常用方法。
java
// 1. 定义实体 (User.java)
@Data // Lombok 简化 getter/setter
@TableName("sys_user") // 指定表名(如果表名 != 类名)
public class User {
@TableId(type = IdType.AUTO) // 主键策略:数据库自增
private Long id;
private String username;
private String password;
private String email;
private Integer status;
}
// 2. 你的 Mapper 接口,只需继承 BaseMapper,指定泛型为你的实体
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 无需再写 insert, selectById, updateById, deleteById 等方法声明!
// BaseMapper 已经提供了它们!
}
// 3. 在 Service 或测试中直接使用注入的 userMapper
@Autowired
private UserMapper userMapper;
// 插入一条用户 (自动处理主键、字段映射)
User newUser = new User(null, "zhangsan", "encrypted_pwd", "zs@example.com", 1);
int insertCount = userMapper.insert(newUser); // 返回影响行数
System.out.println("插入成功,ID为: " + newUser.getId()); // 自增ID回填
// 根据ID查询
User user = userMapper.selectById(1L);
// 根据ID更新 (注意:更新哪个字段,取决于你的 user 对象哪些属性不为null)
User updateUser = new User();
updateUser.setId(1L);
updateUser.setEmail("new_email@example.com");
int updateCount = userMapper.updateById(updateUser);
// 根据ID删除
int deleteCount = userMapper.deleteById(1L);
上述中有一个Lombok 简化 getter/setter,如果不知道Lombok的请看我这篇的介绍
BaseMapper类内部已经都封装好了比如添加,删除,查询,更新这些方面,直接调用就行。

优势: 省去所有基础 CRUD 的接口声明和 XML 编写!字段映射、SQL 生成 MP 全包了。
秘籍 2:IService / ServiceImpl - 服务层增强
核心思想: 服务层接口继承 IService<T>
,实现类继承 ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>
,获得更强的业务封装能力。

优势: 服务层也无需写基础 CRUD 实现,代码更简洁,业务逻辑更集中。 有很多方法可以直接使用

秘籍 3:条件构造器 - 复杂查询的利器
核心思想: 告别手写 WHERE
条件!使用 QueryWrapper
或更类型安全的 LambdaQueryWrapper
来动态构建查询、更新、删除条件。这是 MP 的灵魂之一。
java
// 场景1:查询状态为1、用户名包含"admin"、邮箱不为空的用户列表 (使用 LambdaQueryWrapper,类型安全,推荐!)
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.eq(User::getStatus, 1)
.like(User::getUsername, "admin")
.isNotNull(User::getEmail)
.orderByDesc(User::getId);
List<User> userList = userMapper.selectList(lambdaQuery); // 或 userService.list(lambdaQuery)
// 生成的 SQL 类似:SELECT ... FROM sys_user WHERE status = 1 AND username LIKE '%admin%' AND email IS NOT NULL ORDER BY id DESC
// 场景2:更新所有状态为0的用户,将其密码重置为'default_pwd'
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(User::getPassword, "default_pwd")
.eq(User::getStatus, 0);
int updateCount = userMapper.update(null, updateWrapper); // 第一个参数为 null 表示不更新实体字段,只按 Wrapper 更新
// 生成的 SQL 类似:UPDATE sys_user SET password = 'default_pwd' WHERE status = 0
// 场景3:删除邮箱以 'test_' 开头的测试用户
LambdaQueryWrapper<User> deleteWrapper = new LambdaQueryWrapper<>();
deleteWrapper.likeRight(User::getEmail, "test_"); // 'test_%'
int deleteCount = userMapper.delete(deleteWrapper);
优势: 用 Java 代码优雅地构建复杂 SQL 条件,避免 SQL 注入,代码可读性强,易于维护。LambdaQueryWrapper
利用方法引用,编译时就能检查字段名正确性,极大减少拼写错误。
秘籍 4:分页插件 - 分页如此简单
核心思想: 配置一个分页拦截器 (PaginationInnerInterceptor
),就能让你的查询方法轻松支持物理分页。
java
// 1. 配置分页插件 (通常在 MyBatisPlusConfig 配置类中)
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 根据数据库类型选择
return interceptor;
}
}
// 2. 在 Mapper 或 Service 中使用 Page 对象进行分页查询
// Service 层方式 (推荐)
Page<User> pageParam = new Page<>(1, 10); // 查询第1页,每页10条
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, 1);
Page<User> userPage = userService.page(pageParam, queryWrapper); // 核心分页方法
System.out.println("总记录数: " + userPage.getTotal());
System.out.println("总页数: " + userPage.getPages());
System.out.println("当前页数据: " + userPage.getRecords());
// Mapper 方式
Page<User> pageParam = new Page<>(1, 10);
LambdaQueryWrapper<User> queryWrapper = ...;
Page<User> userPage = userMapper.selectPage(pageParam, queryWrapper);
优势: 一行配置 + 一个 Page
参数,复杂的分页查询瞬间搞定,返回结果包含分页所有信息。
三、总结:高效秘籍的精髓
MyBatis-Plus 的 CRUD 增强秘籍,其核心精髓在于 "约定优于配置" 和 "强大的自动化":
- BaseMapper: 基础 CRUD 的自动化,告别重复声明和手写 SQL。
- IService/ServiceImpl: 服务层通用逻辑的封装,提升业务代码纯度。
- Wrapper (Lambda): 用类型安全的 Java 代码动态构建复杂 SQL 条件,安全高效。
- 分页插件: 极简配置实现标准分页功能。
四、如何使用?
要使用的话,千万还得记得在pom.xml文件中进行包的配置,不然的话写出来是会报错的
以SpringBoot为例,配置参数如下:

xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>