手把手玩转MyBatis-Plus条件构造器:告别硬编码,解锁丝滑数据库操作
一、为什么你需要条件构造器?
想象一下这个场景:你要从用户表里筛选出名字带”张”、年龄在20-30岁之间,并且最近一个月登录过的用户。如果手写 SQL,光是处理动态条件就得写一堆if判断,不仅麻烦还容易出错。MyBatis-Plus 的条件构造器(Wrapper)就是你的救星!
它能帮你:
✅ 用链式调用代替繁琐的 SQL 拼接
✅ 避免字段名硬编码引发的低级错误
✅ 轻松实现动态查询/更新条件
二、四大金刚:条件构造器全家桶
1. QueryWrapper:直男型操作
- 特点:直接写字段名,适合快速上手
- 示例:找名字叫”John”的程序员小哥
1 | QueryWrapper<User> wrapper = new QueryWrapper<>(); |
坑点警告:字段名写错不会报错,直到运行时爆炸!💥
2. LambdaQueryWrapper:智能防呆款
- 特点:用 Lambda 表达式引用字段,妈妈再也不用担心我拼错字段名
- 示例:查找年龄≥25岁的VIP用户
1 | LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); |
为什么香?
👉 编译时检查字段名,把Bug扼杀在摇篮里
👉 代码自带注释效果,一看 User::getAge 就知道查的是年龄
3. UpdateWrapper:改数据小能手
- 特点:专门负责数据更新,能直接设置新值
- 示例:给技术部全员加薪500
1 | UpdateWrapper<User> wrapper = new UpdateWrapper<>(); |
适用场景:批量调整数据,比如调价、状态批量变更
4. LambdaUpdateWrapper:升级版改数据
- 特点:UpdateWrapper + Lambda 双buff加持
- 示例:重置未激活用户的密码
1 | LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>(); |
优势对比:
| 操作 | 传统写法 | Lambda写法 |
|---|---|---|
| 字段名引用 | 手写字符串(易错) | 自动推导(防呆) |
| 改密码字段 | .set("password", "123") |
.set(User::getPassword, "123") |
三、实战教学:从青铜到王者
场景1:动态搜索过滤器
需求:前端传参可能包含 name、minAge、maxAge,要根据参数动态查询
1 | public List<User> search(String name, Integer minAge, Integer maxAge) { |
技巧:
🔹 like(condition, 字段, 值) 自动跳过空条件
🔹 多个条件默认用 AND 连接
场景2:复杂更新逻辑
需求:给部门A的员工发奖金,但排除实习生
1 | LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>(); |
点睛之笔:
👉 用 .setSql() 处理复杂计算
👉 链式调用一气呵成,比XML配置清爽10倍!
场景3:联表查询骚操作
需求:查询用户信息时带出部门名称(虽然MP不直接支持联表,但可以变通)
1 | @Select("SELECT u.*, d.name as dept_name FROM user u LEFT JOIN dept d ON u.dept_id=d.id ${ew.customSqlSegment}") |
划重点:
🔸 ${ew.customSqlSegment} 会自动拼接 WHERE 条件
🔸 实体类加 @TableField(exist = false) 标记非数据库字段
四、避坑指南:血泪经验总结
1. NPE 防护
错误示范:
1 | wrapper.eq(User::getName, params.getName()); // 如果name为null就GG |
正确姿势:
1 | wrapper.eq(params.getName() != null, User::getName, params.getName()); |
2. 日期处理
坑点:直接传 new Date() 可能类型不匹配
解决方案:
1 | wrapper.ge(User::getCreateTime, LocalDateTime.now().minusDays(7)); // 查最近7天的数据 |
3. 批量操作
错误姿势:在循环里逐条更新
正确姿势:
1 | LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>(); |
五、性能优化秘籍
- 索引加持:高频查询字段记得加数据库索引
- 拒绝全表扫描:
1 | // 坏味道 ❌ |
- 分页优化:
1 | Page<User> page = new Page<>(1, 10).setSearchCount(false); // 不查总数提升速度 |
六、总结:怎么选最适合的Wrapper?
| 场景 | 推荐工具 | 原因 |
|---|---|---|
| 简单查询 | LambdaQueryWrapper | 避免字段名手误 |
| 复杂更新 | LambdaUpdateWrapper | 类型安全 + 链式更新 |
| 需要直接写字段名 | QueryWrapper/UpdateWrapper | 处理特殊字段或复杂表达式 |
| 动态条件 | 所有Wrapper的condition参数 | 自动跳过空条件 |
终极口诀:
👉 能用 Lambda 就别用手写字段名
👉 条件越动态,Wrapper 越香
👉 复杂查询不要硬扛,该用XML就用XML
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Luminous の Space!
