Skip to content

条件构造器(Wrapper) ​

  条件构造器是 MyBatis-Plus 最强大的特性之一,让你用 Lambda 表达式构建 SQL WHERE 条件,类型安全,告别字符串硬编码。

一、四种 Wrapper 对比 ​

Wrapper用途字段引用方式推荐度
QueryWrapper条件查询字符串 "name"一般
UpdateWrapper条件更新字符串 "name"一般
LambdaQueryWrapper条件查询Lambda User::getName推荐
LambdaUpdateWrapper条件更新Lambda User::getAge推荐
java
// 字符串方式(不推荐:字段名拼错编译期发现不了)
QueryWrapper<User> qw = new QueryWrapper<>();
qw.eq("name", "张三");  // "name" 写错了编译不报错

// Lambda 方式(推荐:字段名由编译器检查)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.eq(User::getName, "张三");  // 写错了编译就报错

二、LambdaQueryWrapper 条件方法 ​

2.1 比较条件 ​

java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

// 等于 =
wrapper.eq(User::getName, "张三");

// 不等于
wrapper.ne(User::getAge, 25);

// 大于 >
wrapper.gt(User::getAge, 20);

// 大于等于 >=
wrapper.ge(User::getAge, 18);

// 小于 <
wrapper.lt(User::getAge, 60);

// 小于等于 <=
wrapper.le(User::getAge, 60);

2.2 模糊查询 ​

java
// LIKE '%张%'
wrapper.like(User::getName, "张");

// LIKE '%张'(左模糊)
wrapper.likeLeft(User::getName, "张");

// LIKE '张%'(右模糊)
wrapper.likeRight(User::getName, "张");

2.3 范围查询 ​

java
// BETWEEN 值1 AND 值2
wrapper.between(User::getAge, 20, 30);

// NOT BETWEEN
wrapper.notBetween(User::getAge, 20, 30);

// IN (1, 2, 3)
wrapper.in(User::getId, Arrays.asList(1L, 2L, 3L));

// NOT IN
wrapper.notIn(User::getId, Arrays.asList(1L, 2L, 3L));

2.4 空值判断 ​

java
// IS NULL
wrapper.isNull(User::getEmail);

// IS NOT NULL
wrapper.isNotNull(User::getEmail);

2.5 分组与排序 ​

java
// GROUP BY
wrapper.groupBy(User::getAge);

// HAVING
wrapper.having("COUNT(*) > {0}", 5);

// ORDER BY ASC
wrapper.orderByAsc(User::getAge);

// ORDER BY DESC
wrapper.orderByDesc(User::getCreateTime);

// 多字段排序
wrapper.orderByAsc(User::getAge)
       .orderByDesc(User::getCreateTime);

2.6 逻辑组合 ​

java
// AND 嵌套(默认就是 AND)
wrapper.eq(User::getName, "张三")
       .eq(User::getAge, 25);

// OR
wrapper.eq(User::getName, "张三")
       .or()
       .eq(User::getName, "李四");
// WHERE name = '张三' OR name = '李四'

// AND 嵌套(括号)
wrapper.eq(User::getName, "张三")
       .and(w -> w.eq(User::getAge, 25).or().eq(User::getAge, 30));
// WHERE name = '张三' AND (age = 25 OR age = 30)

// OR 嵌套
wrapper.eq(User::getName, "张三")
       .or(w -> w.eq(User::getAge, 25).eq(User::getEmail, "test@test.com"));
// WHERE name = '张三' OR (age = 25 AND email = 'test@test.com')

2.7 条件 SQL ​

java
// 直接拼接 SQL(慎用)
wrapper.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", "2024-01-01");

// 自定义 SQL 片段
wrapper.last("LIMIT 1");  // 拼接到最后
wrapper.exists("SELECT 1 FROM order WHERE user_id = user.id");  // EXISTS 子查询

三、实战场景 ​

3.1 动态条件查询 ​

java
public List<User> searchUsers(String name, Integer minAge, Integer maxAge, String email) {
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

    // 只有参数不为空时才添加条件
    wrapper.like(StringUtils.hasText(name), User::getName, name)
           .ge(minAge != null, User::getAge, minAge)
           .le(maxAge != null, User::getAge, maxAge)
           .eq(StringUtils.hasText(email), User::getEmail, email)
           .orderByDesc(User::getCreateTime);

    return userMapper.selectList(wrapper);
}

关键: 第一个参数 boolean condition 控制是否添加该条件,为 false 时跳过。

3.2 复杂条件查询 ​

java
// 查询:name 包含"张" 且 (age < 20 或 age > 60) 且 email 不为空
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "张")
       .and(w -> w.lt(User::getAge, 20).or().gt(User::getAge, 60))
       .isNotNull(User::getEmail);

List<User> users = userMapper.selectList(wrapper);
// SQL: SELECT * FROM user
//      WHERE name LIKE '%张%'
//      AND (age < 20 OR age > 60)
//      AND email IS NOT NULL

3.3 只查部分字段 ​

java
// 只查 id 和 name
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.select(User::getId, User::getName)
       .eq(User::getAge, 25);

List<User> users = userMapper.selectList(wrapper);
// SQL: SELECT id, name FROM user WHERE age = 25

3.4 排除某字段 ​

java
// 查除了 email 以外的所有字段
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.select(User.class, info -> !info.getColumn().equals("email"));

四、LambdaUpdateWrapper ​

java
// 修改 name 为"张三"的用户的 age 为 30
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.set(User::getAge, 30)
       .set(User::getEmail, "new@test.com")
       .eq(User::getName, "张三");

userMapper.update(null, wrapper);
// UPDATE user SET age = 30, email = 'new@test.com' WHERE name = '张三'
java
// 根据条件动态更新
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(User::getName, "张三");

if (newAge != null) {
    wrapper.set(User::getAge, newAge);
}
if (newEmail != null) {
    wrapper.set(User::getEmail, newEmail);
}

userMapper.update(null, wrapper);

五、常用条件速查表 ​

方法含义SQL 等价
eq等于=
ne不等于<>
gt大于>
ge大于等于>=
lt小于<
le小于等于<=
like模糊LIKE '%值%'
likeLeft左模糊LIKE '%值'
likeRight右模糊LIKE '值%'
between区间BETWEEN 值1 AND 值2
in包含IN (值1, 值2)
isNull为空IS NULL
isNotNull不为空IS NOT NULL
orderByAsc升序ORDER BY ASC
orderByDesc降序ORDER BY DESC
groupBy分组GROUP BY
having分组过滤HAVING
and逻辑与AND
or逻辑或OR

六、速记总结 ​

条件构造器选择:
  LambdaQueryWrapper  → 查询用
  LambdaUpdateWrapper → 更新用

动态条件写法:
  wrapper.eq(condition, 字段, 值)
  第一个参数 = false → 跳过该条件

嵌套逻辑:
  .and(w -> w.条件1.or().条件2)  → (条件1 OR 条件2)
  .or(w -> w.条件1.条件2)        → OR (条件1 AND 条件2)

速记口诀:
  Lambda 写条件,类型安全编译检,
  eq 等于 ne 不等,gt 大于 lt 小于,
  like 模糊 between 区间,in 包含 null 判空,
  and 嵌套 or 嵌套,condition 做前置。

七、面试要点 ​

问题答案要点
为什么推荐 Lambda 方式?类型安全,字段名编译期检查,防止拼写错误
怎么实现动态条件?第一个参数 boolean condition 控制
如何嵌套 OR 条件?.and(w -> w.xxx.or().xxx)