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)