MP 条件构造器:LambdaQueryWrapper 常用写法
上一章的 selectList(null) 只能查全表,条件查询靠条件构造器 Wrapper。它的价值是类型安全:用 Lambda 表达式写列名,编译期防拼错。本节梳理 LambdaQueryWrapper 与 LambdaUpdateWrapper 的常用写法。
三种构造方式
LambdaQueryWrapper<User> w1 = new LambdaQueryWrapper<>(); // new
LambdaQueryWrapper<User> w2 = Wrappers.lambdaQuery(); // 静态工厂
List<User> list = userService.lambdaQuery().eq(...).list(); // Service 链式
选一种风格固定使用,团队内别混。
常用条件方法
| 需求 | 写法 |
|---|---|
| 等于/不等于 | .eq(User::getName, "小明") / .ne(...) |
| 大于/小于等于 | .gt(User::getAge, 18) / .le(...) |
| 区间 | .between(User::getCreateTime, start, end) |
| 模糊 | .like(User::getName, "明")(值里不用带 %) |
| 集合内 | .in(User::getStatus, 1, 2, 3) |
| 为空判断 | .isNull(User::getDeleted) / .isNotNull(...) |
组合示例:"状态启用且姓名含'张',按创建时间倒序":
List<User> list = userMapper.selectList(
Wrappers.<User>lambdaQuery()
.eq(User::getStatus, 1)
.like(User::getName, "张")
.orderByDesc(User::getCreateTime));
判空条件:condition 参数
"前端没传就不查"是最高频需求,Wrapper 的第一个参数就是条件开关:
LambdaQueryWrapper<User> w = Wrappers.lambdaQuery();
w.eq(name != null && !name.isEmpty(), User::getName, name); // 成立才拼
w.eq(status != null, User::getStatus, status);
List<User> list = userMapper.selectList(w);
比手写一串 if 再拼接干净,也不会漏掉 else 分支。
and/or 分组与高级写法
or 的优先级最易错:a or (b and c) 要显式分组,用 and(...) 传入子构造器:
// WHERE status = 1 AND (age > 18 OR name LIKE '%张%')
w.eq(User::getStatus, 1).and(q ->
q.gt(User::getAge, 18).or().like(User::getName, "张"));
其他常用:
w.select(User::getId, User::getName); // 投影:只查两列
w.groupBy(User::getDeptId).having("count(*) > 5"); // 分组过滤
w.last("LIMIT 10"); // 追加 SQL,谨慎使用
更新构造器与安全提醒
LambdaUpdateWrapper 直接按条件更新,避免先查后改:
int rows = userMapper.update(null,
Wrappers.<User>lambdaUpdate()
.set(User::getStatus, 0) // SET status = 0
.eq(User::getDeptId, 10)); // WHERE dept_id = 10
两个提醒:Wrapper 的值参数仍走预编译绑定,安全;但 last()、apply("...") 这类能拼 SQL 片段的方法若拼接用户输入,等价于 SQL 拼接,必须白名单——安全纪律与手写 SQL 完全一致(见注入防护一章)。
LambdaQueryWrapper 把"写条件"从字符串变成编译期检查的 Lambda,配合 condition 参数天然支持可选条件。先记熟 eq / like / in / between / orderBy / and 分组六个动作,绝大多数查询就够用了。