一、核心定位:什么是 Wrapper?
Wrapper 是 MP 提供的条件构造器顶层接口,所有条件构造器都实现了这个接口。它的本质是:
- 把 SQL 的
WHERE条件(比如username = ? AND status = 1)转换成 Java 代码的链式调用; - 最终 MP 会自动把
Wrapper拼接成对应的 SQL 条件,无需手写 XML 条件判断。
二、常用实现类(重点记这 3 个)
Wrapper 是顶层接口,实际开发中不会直接用,而是用它的子类,核心有 3 个:
表格
| 实现类 | 核心特点 | 适用场景 |
|---|---|---|
QueryWrapper |
通用查询条件构造器,支持所有 SQL 条件(=、>、<、LIKE、IN 等) | 单表查询(最常用) |
UpdateWrapper |
专用更新条件构造器,支持 SET 字段赋值 + WHERE 条件 |
单表更新 / 删除 |
LambdaQueryWrapper |
基于 Lambda 的查询构造器,字段名用「类::属性」,避免硬编码字段名(推荐) | 所有单表查询(更优雅、无错) |
2.1QueryWrapper:查询条件构造器
2.1.1方法
| 方法名 | 对应 SQL 语法 | 核心作用 | 典型使用场景 |
|---|---|---|---|
eq |
= |
精准匹配某一字段等于指定值,是最基础、最常用的等值查询条件 | 查询用户名 ="admin"、状态 = 1、性别 ="男" 等精准条件 |
ne |
!= |
匹配某一字段不等于指定值,排除特定值的记录 | 查询状态≠0(排除禁用用户)、年龄≠18 等排除条件 |
gt |
> |
匹配某一字段大于指定值,仅适用于数值 / 日期类型字段 | 查询年龄 > 18、创建时间 > 2024-01-01 等范围条件 |
lt |
< |
匹配某一字段小于指定值,仅适用于数值 / 日期类型字段 | 查询年龄 < 60、金额 < 1000 等范围条件 |
like |
LIKE |
模糊匹配字符串字段,默认拼接 %值%(包含匹配),可扩展 likeLeft/likeRight like 扩展: * likeLeft:拼接 值%(左匹配,如手机号以 138 开头); * likeRight:拼接 %值(右匹配,如邮箱以 @163.com结尾)。 |
查询用户名含 "张"、手机号以 "138" 开头等模糊查询 |
in |
IN |
匹配某一字段值在指定的集合 / 多值范围内,替代多个 OR 拼接 |
查询 ID 在 [1,2,3]、状态在 [1,2] 等多值匹配条件 |
isNull |
IS NULL |
匹配某一字段值为 null 的记录,对应反向方法 isNotNull(IS NOT NULL) |
查询手机号为空、邮箱未填写等空值判断条件 |
2.1.2方法举例
1. eq(字段=值 匹配)
/**
* 需求:查询用户名等于"admin"的用户
* 对应SQL:SELECT * FROM sys_user WHERE username = 'admin'
*/
public List<SysUser> testEq() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getUsername, "admin"); // 字段=值
return sysUserMapper.selectList(wrapper);
}
2. ne(!= 不等值匹配)
/**
* 需求:查询状态不等于0(未禁用)的用户
* 对应SQL:SELECT * FROM sys_user WHERE status != 0
*/
public List<SysUser> testNe() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.ne(SysUser::getStatus, 0); // 字段!=值
return sysUserMapper.selectList(wrapper);
}
3. gt(> 大于)
/**
* 需求:查询年龄大于18的用户
* 对应SQL:SELECT * FROM sys_user WHERE age > 18
*/
public List<SysUser> testGt() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(SysUser::getAge, 18); // 字段>值
return sysUserMapper.selectList(wrapper);
}
4. lt(< 小于)
/**
* 需求:查询年龄小于60的用户
* 对应SQL:SELECT * FROM sys_user WHERE age < 60
*/
public List<SysUser> testLt() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.lt(SysUser::getAge, 60); // 字段<值
return sysUserMapper.selectList(wrapper);
}
5. like(模糊匹配)
/**
* 需求1:查询用户名包含"张"的用户(默认%值%)
* 对应SQL:SELECT * FROM sys_user WHERE username LIKE '%张%'
* 扩展:likeLeft(值%)= 以"张"开头;likeRight(%值)= 以"张"结尾
*/
public List<SysUser> testLike() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.like(SysUser::getUsername, "张"); // 模糊匹配包含"张"
// wrapper.likeLeft(SysUser::getPhone, "138"); // 手机号以138开头
return sysUserMapper.selectList(wrapper);
}
6. in(IN 多值匹配)
/**
* 需求:查询ID在1、2、3范围内的用户
* 对应SQL:SELECT * FROM sys_user WHERE id IN (1,2,3)
*/
public List<SysUser> testIn() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
// 方式1:传集合
List<Long> ids = Arrays.asList(1L, 2L, 3L);
wrapper.in(SysUser::getId, ids);
// 方式2:直接传多个值
// wrapper.in(SysUser::getStatus, 1, 2); // 状态在1、2范围内
return sysUserMapper.selectList(wrapper);
}
7. isNull(IS NULL 空值匹配)
/**
* 需求:查询手机号为空的用户
* 对应SQL:SELECT * FROM sys_user WHERE phone IS NULL
* 扩展:isNotNull = phone IS NOT NULL(手机号不为空)
*/
public List<SysUser> testIsNull() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.isNull(SysUser::getPhone); // 字段为null
// wrapper.isNotNull(SysUser::getPhone); // 字段不为null
return sysUserMapper.selectList(wrapper);
}
8.orderByDesc() - 按照字段名降序

9.orderByASC() - 按照字段名升序

扩展:多条件组合示例(实战高频)
/**
* 需求:查询年龄>18 且 状态=1 且 用户名含"张"的用户
* 对应SQL:SELECT * FROM sys_user WHERE age > 18 AND status = 1 AND username LIKE '%张%'
*/
public List<SysUser> testMultiCondition() {
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(SysUser::getAge, 18)
.eq(SysUser::getStatus, 1)
.like(SysUser::getUsername, "张");
return sysUserMapper.selectList(wrapper);
}
2.1.3 中间以and连接

2.2UpdateWrapper类
2.2.0核心优势
官方明确其核心优势是支持将字段值设为 null(区别于 "实体 + QueryWrapper" 的更新方式)。
2.2.1核心方法
| 方法 | 作用 | 示例 |
|---|---|---|
set() |
拼接 SET 子句,指定要更新的字段和值 |
set("password", "123456") |
| 条件方法 | 拼接 WHERE 子句(和 QueryWrapper 一致) |
eq("username", "admin")、in("id", 1,2) |
entity=null : 指的是本次更新操作完全由UpdateWrapper来指定更新的字段和值,不使用entity中的任何属性。
bash
@Test
public void testUpdateWithWrapper(){
UpdateWrapper updateWrapper = new UpdateWrapper();
updateWrapper.set("tiger_name", "王虎-更新");
updateWrapper.eq("tiger_age", 8);
tigerMapper.update(null, updateWrapper);//entity = null 指的是:本次更新操作完全由 UpdateWrapper 来指定要更新的字段和值,不使用实体类 entity 中的任何属性。
System.out.println("更新成功!");
}
2.2.2拼接方法

2.3LambdaWrapper
2.3.0修改的地方
Lambda 系列 Wrapper 是官方为解决 "硬编码字段名" 问题设计的增强版,基于 Lambda 表达式引用实体类属性,支持编译期字段校验(字段名拼写错误直接编译失败),是生产环境首选。

2.3.1LambdaQueryWrapper :Lambda 风格查询构造器
bash
@Autowired
private TigerMapper tigerMapper;
// 1. 方式1:直接new实例(类型安全,无硬编码)
LambdaQueryWrapper<Tiger> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 拼接条件:tiger_age = 5 AND tiger_name LIKE '%虎%'(引用实体属性,IDE自动补全)
lambdaQueryWrapper.eq(Tiger::getTigerAge, 5)
.like(Tiger::getTigerName, "虎")
.gt(Tiger::getTigerSalary, 500);
// 2. 方式2:Wrappers工具类(官方推荐,简化代码)
LambdaQueryWrapper<Tiger> lambdaQueryWrapper2 = Wrappers.lambdaQuery();
lambdaQueryWrapper2.ne(Tiger::getTigerAge, 3)
.isNotNull(Tiger::getTigerSalary)
.orderByDesc(Tiger::getTigerAge);
// 3. 执行查询(与普通Wrapper调用方式一致)
List<Tiger> tigerList = tigerMapper.selectList(lambdaQueryWrapper);
2.3.2LambdaUpdateWrapper :Lambda 风格更新构造器
bash
@Autowired
private TigerMapper tigerMapper;
// 1. 方式1:直接new实例(无硬编码字段名)
LambdaUpdateWrapper<Tiger> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
// 拼接更新逻辑:SET tiger_name = 'Lambda虎', tiger_salary = 600 WHERE tiger_id = 1
lambdaUpdateWrapper.set(Tiger::getTigerName, "Lambda虎")
.set(Tiger::getTigerSalary, 600.00)
.eq(Tiger::getTigerId, 1);
// 2. 方式2:Wrappers工具类(官方推荐)
LambdaUpdateWrapper<Tiger> lambdaUpdateWrapper2 = Wrappers.lambdaUpdate();
// 拼接更新逻辑:SET tiger_age = tiger_age + 1 WHERE tiger_name = '李虎'
lambdaUpdateWrapper2.setSql("tiger_age = tiger_age + 1") // 支持原生SQL片段
.eq(Tiger::getTigerName, "李虎");
// 3. 执行更新
int affectedRows = tigerMapper.update(null, lambdaUpdateWrapper);
2.3.3支持setSql的原生SQL语句
bash
lambdaUpdateWrapper2.setSql("tiger_age = tiger_age + 1") // 支持原生SQL片段
.eq(Tiger::getTigerName, "李虎");
2.4普通Wrapper和LambdaWrapper的对比
| 字段引用方式 | 优缺点 | 适用场景 |
|-------------------|---------------------------------------|---------------------|-------------|
| 普通 Wrapper | 数据库字段名字符串(如 "tiger_name") | 灵活但易拼写错误,运行时暴露问题 | 快速测试、简单场景 |
| Lambda 系列 Wrapper | 实体属性 Lambda 引用(如 Tiger::getTigerName) | 类型安全、编译期校验,官方推荐生产使用 | 生产环境、复杂业务场景 |
三、实战用法(结合你的用户登录 / 查询场景)
以你熟悉的 SysUser 表为例,演示 3 种常用写法:
1. 基础用法:QueryWrapper(硬编码字段名)
// 需求:查询 用户名=admin 且 状态=1 的用户
@Service
public class UserServiceImpl implements UserService {
@Autowired
private SysUserMapper userMapper;
@Override
public SysUser findUser(String username) {
// 1. 创建查询构造器
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
// 2. 链式拼接条件(等价于 WHERE username = ? AND status = 1)
wrapper.eq("username", username) // eq = equal,等于
.eq("status", 1); // 多条件默认用 AND 连接
// 3. 调用 MP 通用方法,传入 wrapper
return userMapper.selectOne(wrapper);
}
}
2. 推荐用法:LambdaQueryWrapper(避免字段名硬编码)
@Override
public SysUser findUser(String username) {
// Lambda 方式:字段名用 SysUser::getUsername,编译期校验,不会拼错
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysUser::getUsername, username)
.eq(SysUser::getStatus, 1);
return userMapper.selectOne(wrapper);
}
✅ 优势:如果数据库字段名改了(比如 username → user_name),只要实体类属性名没改,代码不用动;硬编码写法会直接报错。
3. 更新用法:UpdateWrapper
// 需求:把 admin 用户的密码改成 123456,且状态=1
@Override
public boolean updateUserPassword(String username) {
UpdateWrapper<SysUser> wrapper = new UpdateWrapper<>();
// SET 子句:设置要更新的字段
wrapper.set("password", "123456")
// WHERE 子句:更新条件
.eq("username", username)
.eq("status", 1);
// 调用 MP 通用更新方法
return userMapper.update(null, wrapper) > 0;
}
四、核心优势(对比传统 MyBatis)
表格
| 传统 MyBatis(XML) | MyBatis Plus(Wrapper) |
|---|---|
手写 <if>/<where> 标签 |
一行链式调用搞定,无需 XML |
| 字段名硬编码(易拼错) | Lambda 方式编译期校验(字段名不会错) |
| 动态条件需写大量 XML | 动态条件用 if 包裹链式调用即可 |
| 多表联查需手写 SQL | 单表查询极致简洁,多表联查仍需手写 SQL |
五、常用条件方法(速查)
表格
| Wrapper 方法 | SQL 等价条件 | 示例 |
|---|---|---|
eq |
= |
eq("username", "admin") |
ne |
!= |
ne("status", 0) |
gt |
> |
gt("age", 18) |
like |
LIKE |
like("username", "%admin%") |
in |
IN |
in("id", 1,2,3) |
and |
AND |
多条件默认 AND |
or |
OR |
or().eq("status", 2) |
总结
Wrapper是 MP 条件构造器的顶层接口,核心子类是QueryWrapper/LambdaQueryWrapper/UpdateWrapper;- 优先用
LambdaQueryWrapper:避免字段名硬编码,编译期校验,最优雅; - 核心价值:用 Java 代码链式拼接 SQL 条件,替代 XML 中的
<if>/<where>,简化单表条件查询 / 更新。