MyBatis-Plus 从入门到高级完整总结
·
MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 基础上只做增强不做修改,简化单表操作、提升开发效率,是国内企业级开发主流持久层框架。
一、基础入门(环境搭建 + 核心使用)
1. 核心依赖(Maven)
xml
<!-- SpringBoot 整合 MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 数据库驱动(以 MySQL 为例) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2. 核心配置(application.yml)
yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: 账号
password: 密码
# MyBatis-Plus 配置
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 开启下划线转驼峰(默认开启)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印 SQL 日志
global-config:
db-config:
id-type: auto # 全局主键自增策略
3. 核心注解(实体类映射)
表格
| 注解 | 作用 |
|---|---|
@TableName("表名") | 实体类对应数据库表名 |
@TableId | 标记主键字段 |
@TableField("字段名") | 实体属性对应表字段 |
@TableField(exist = false) | 标记非数据库字段 |
示例实体类:
@Data
@TableName("t_user") // 对应数据库表 t_user
public class User {
@TableId(type = IdType.AUTO) // 主键自增
private Long id;
@TableField("user_name") // 对应表字段 user_name
private String userName;
private Integer age;
@TableField(exist = false) // 数据库无此字段
private String temp;
}
4. 核心 Mapper 接口(基础 CRUD)
继承 BaseMapper<T>,无需写 XML,直接拥有单表 CRUD:
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 无需编写方法,直接使用父类 CRUD
}
5. 基础 CRUD 方法
// 1. 新增
userMapper.insert(user);
// 2. 根据 ID 查询
User user = userMapper.selectById(1L);
// 3. 条件查询
List<User> list = userMapper.selectList(null); // 查询全部
// 4. 根据 ID 修改
userMapper.updateById(user);
// 5. 根据 ID 删除
userMapper.deleteById(1L);
二、中级进阶(条件构造器 + 分页 + 逻辑删除)
1. 强大的条件构造器 QueryWrapper/LambdaQueryWrapper
MP 核心功能,零 SQL 实现复杂条件查询,推荐用 LambdaQueryWrapper(防字段名写错)。
常用条件:
eq:等于ne:不等于gt:大于ge:大于等于lt:小于le:小于等于like:模糊查询between:区间查询orderByAsc/Desc:排序
示例:
// Lambda 条件构造器(推荐)
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getAge, 20) // 年龄=20
.like(User::getUserName, "张") // 用户名含"张"
.between(User::getId, 1, 10) // ID 1-10
.orderByDesc(User::getId); // 按 ID 降序
List<User> list = userMapper.selectList(wrapper);
2. 分页查询(最完整实战版)
1)配置分页插件(SpringBoot)
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
// 防止全表溢出
paginationInterceptor.setOverflow(true);
// 最大单页限制
paginationInterceptor.setMaxLimit(1000L);
interceptor.addInnerInterceptor(paginationInterceptor);
return interceptor;
}
}
2)基础分页
// 第 1 页,每页 10 条
Page<User> page = new Page<>(1, 10);
// 条件
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getAge, 20);
// 执行
Page<User> result = userMapper.selectPage(page, wrapper);
// 结果
List<User> records = result.getRecords(); // 当前页数据
long total = result.getTotal(); // 总条数
long pages = result.getPages(); // 总页数
long current = result.getCurrent(); // 当前页
long size = result.getSize(); // 每页条数
3)VO 分页(最常用)
Page<UserVO> voPage = result.convert(user -> {
UserVO vo = new UserVO();
vo.setId(user.getId());
vo.setName(user.getUserName());
return vo;
});
3. 逻辑删除(企业必开)
作用:
-
不真正删除数据,只做标记
-
查询时自动过滤已删除数据
1)数据库加字段
ALTER TABLE t_user ADD COLUMN deleted TINYINT DEFAULT 0;
2)实体类标记
@TableLogic
private Integer deleted;
3)全局配置(推荐)
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1 # 已删除
logic-not-delete-value: 0 # 未删除
效果
deleteById(1L)→ 变成UPDATE ... SET deleted=1selectById(1L)→ 自动拼接AND deleted=0
4. 自动填充(create_time、update_time)
1)实体类
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
2)配置填充器
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime::now, LocalDateTime.class);
this.strictInsertFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::now, LocalDateTime.class);
}
}
效果
- insert → 自动填 createTime、updateTime
- update → 自动更新 updateTime
三、高级篇(企业级必备)
1. 批量操作(性能提升巨大)
MP 提供 IService 层,自带批量方法,比循环单条快 10~100 倍。
1)定义 Service
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
2)常用批量方法
// 批量新增
userService.saveBatch(userList);
// 分批新增(推荐大数据量)
userService.saveBatch(userList, 1000);
// 批量修改
userService.updateBatchById(userList);
// 批量删除
userService.removeByIds(Arrays.asList(1L,2L,3L));
3)批量插入原理
- 默认:拼一条 INSERT INTO ... VALUES (...),(...)
- 大列表:自动分批,防止 SQL 过长
2. 多租户(Saas 系统必备)
作用
- 一套数据库,多个公司 / 用户数据互相隔离
- 所有 SQL 自动拼接
tenant_id = ?
1)添加租户插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
tenantInterceptor.setTenantLineHandler(new TenantLineHandler() {
@Override
public Expression getTenantId() {
// 从登录信息获取租户ID
Long tenantId = 10086L;
return new LongValue(tenantId);
}
@Override
public String getTenantIdColumn() {
return "tenant_id"; // 租户字段
}
// 哪些表忽略租户
@Override
public boolean ignoreTable(String tableName) {
return Arrays.asList("sys_dict").contains(tableName);
}
});
interceptor.addInnerInterceptor(tenantInterceptor);
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
效果
你写:
userMapper.selectList(null);
MP 自动生成:
SELECT * FROM t_user WHERE tenant_id = 10086 AND deleted = 0
3. 性能优化 & 最佳实践(面试高频)
1)禁止全表更新 / 删除(必开)
mybatis-plus:
global-config:
db-config:
block-attack: true
作用:
update(user, null)→ 直接报错- 防止线上事故
2)只查需要的字段
wrapper.select(User::getId, User::getUserName);
3)避免大量循环单条插入
坏的:
for (User user : list) {
userMapper.insert(user);
}
好
userService.saveBatch(list, 1000);
4)SQL 性能分析插件
// 打印慢SQL
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100); // 超过100ms报警
performanceInterceptor.setFormat(true);
interceptor.addInnerInterceptor(performanceInterceptor);
5)枚举自动映射
@Getter
public enum StatusEnum {
NORMAL(0, "正常"),
DISABLE(1, "禁用");
private final Integer code;
private final String desc;
}
@TableField("status")
private StatusEnum status;
自动存 code,自动取转枚举。
6)乐观锁(防并发修改)
@Version
private Integer version;
更新时自动带 version = ?,版本不一致不更新。
四、总结(极简记忆版)
进阶
- 分页:配置插件 + new Page () + selectPage
- 逻辑删除:deleted 字段 + @TableLogic
- 自动填充:FieldFill + MetaObjectHandler
高级
- 批量操作:IService + saveBatch / updateBatchById
- 多租户:TenantLineInnerInterceptor,自动拼 tenant_id
- 性能优化:禁止全表更新、只查需要字段、批量、慢 SQL 监控
更多推荐




所有评论(0)