一、条件构造器MyBatis-PlusMP的核心优势之一就是通过Wrapper体系尤其是QueryWrapper和UpdateWrapper提供了强大、灵活且类型安全的动态 SQL 构建能力特别擅长处理复杂的 WHERE 条件。1-1、AbstractWrapper1、QueryWrapper UpdateWrapperQueryWrapper 在where条件的基础上可以控制多加了select 可选的查询字段。默认是select *1QueryWrapper 示例2updateWrapper示例UpdateWrapper第一个参数传null是因为你不提供实体对象如果你传了实体MP 会把实体中非空字段也加入 SET可能造成意料之外的覆盖。⚠️ 注意事项如果你有实体对象并且想更新它的某些字段 按主键更新也可以用User user new User(); user.setId(1001); user.setNickname(新昵称); userMapper.updateById(user); // 更简洁这种情况不需要UpdateWrapper。小结场景推荐方式按主键更新几个字段updateById(entity)按非主键条件更新update(null, updateWrapper)动态条件/字段更新UpdateWrapper或LambdaUpdateWrapper2、AbstractLambdaWrapper以上的queryWrapper 和 updateWrapper 字段名都是写死的硬编码。二、小结三、QueryWrapper VS UpdateWrapper3-1、一句话区分Wrapper用途核心能力QueryWrapper查询、删除只构造WHERE条件UpdateWrapper更新构造WHERE条件SET更新内容3-2、继承关系AbstractWrapper ← 所有 Wrapper 的基类构造 WHERE ├── QueryWrapper ← 只负责 WHERE ├── UpdateWrapper ← 负责 WHERE SET └── LambdaQueryWrapper / LambdaUpdateWrapper ← 各自对应的 Lambda 版本UpdateWrapper 比 QueryWrapper 多了一个set()方法用来指定要更新的字段和值。3-3、代码对比同一个业务场景场景把年龄大于 30 且状态为禁用的用户状态改为启用。❌ 错误用 QueryWrapper 做更新// QueryWrapper 只能构造 WHERE没法指定 SET 内容 QueryWrapperUser queryWrapper new QueryWrapper(); queryWrapper.gt(age, 30).eq(status, 0); // update() 方法需要传入一个实体对象作为 SET 内容 User user new User(); user.setStatus(1); // 要更新的字段值放在实体里 userMapper.update(user, queryWrapper);缺点实体user中其他字段如果为null配合not_null策略会被忽略但你得new一个对象逻辑上条件和更新内容分离不够直观✅ 正确用 UpdateWrapper 做更新UpdateWrapperUser updateWrapper new UpdateWrapper(); // WHERE 条件年龄 30 且 状态 0 updateWrapper.gt(age, 30).eq(status, 0); // SET 内容直接在这里指定 updateWrapper.set(status, 1); // 还可以同时更新多个字段 updateWrapper.set(update_time, new Date()); userMapper.update(null, updateWrapper);优点条件和更新内容写在一起一目了然第一个参数传null完全不需要 new 实体对象可以更新为nullset(phone, null)不受实体 null 策略影响3-4、什么时候用哪个决策树你要做什么操作 │ ├─→ 查询SELECT─────────────────→ QueryWrapper / LambdaQueryWrapper │ 例list(wrapper)、getOne(wrapper)、count(wrapper) │ ├─→ 删除DELETE─────────────────→ QueryWrapper / LambdaQueryWrapper │ 例remove(wrapper) │ 删除只需要条件不需要 SET │ └─→ 更新UPDATE─────────────────→ UpdateWrapper / LambdaUpdateWrapper 例update(null, wrapper) 更新既需要 WHERE 条件又需要 SET 内容3-5、Lambda 版本推荐实际使用上面用的是字符串硬编码列名容易写错。实际开发强烈推荐 Lambda 版本LambdaQueryWrapper —— 查询/删除// 查询名字包含张且状态启用的用户 LambdaQueryWrapperUser lqw new LambdaQueryWrapper(); lqw.like(User::getUsername, 张) .eq(User::getStatus, 1); ListUser list userMapper.selectList(lqw);LambdaUpdateWrapper —— 更新// 更新id1 的用户只改邮箱和更新时间 LambdaUpdateWrapperUser luw new LambdaUpdateWrapper(); luw.eq(User::getId, 1L) .set(User::getEmail, newqq.com) .set(User::getUpdateTime, new Date()); userMapper.update(null, luw);Lambda 的好处User::getUsername是编译期检查的列名写错直接编译报错不会等到运行时才暴露。3-6、一个完整的实战对比Service public class UserService { Autowired private UserMapper userMapper; // 查询用 QueryWrapper public ListUser getActiveUsersByAge(Integer minAge) { LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.ge(User::getAge, minAge) // WHERE age ? .eq(User::getStatus, 1); // AND status 1 return userMapper.selectList(wrapper); } // 删除用 QueryWrapper public boolean deleteInactiveUsers() { LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getStatus, 0) // WHERE status 0 .lt(User::getCreateTime, LocalDateTime.now().minusYears(1)); // AND create_time 一年前 return userMapper.delete(wrapper) 0; } // 更新用 UpdateWrapper public boolean banUsersByAge(Integer maxAge) { LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper.le(User::getAge, maxAge) // WHERE age ? .eq(User::getStatus, 1) // AND status 1 .set(User::getStatus, 0) // SET status 0 .set(User::getUpdateTime, LocalDateTime.now()); // SET update_time now() return userMapper.update(null, wrapper) 0; } }3-7、容易踩的坑坑说明UpdateWrapper 做查询语法上可行因为继承了 AbstractWrapper但语义不对别这么干QueryWrapper 做更新但没传实体update(null, queryWrapper)→ SET 子句为空SQL 报错UpdateWrapper 传了实体又用了 set()两者会合并实体和 set() 都会进 SET 子句注意别重复忘记update(null, wrapper)第一个参数用 UpdateWrapper 时第一个参数固定传null3-8、速记口诀查删用 Query更新用 Update。Query 只管 WHEREUpdate 还能 SET。
MyBatis-Plus03:条件构造器
一、条件构造器MyBatis-PlusMP的核心优势之一就是通过Wrapper体系尤其是QueryWrapper和UpdateWrapper提供了强大、灵活且类型安全的动态 SQL 构建能力特别擅长处理复杂的 WHERE 条件。1-1、AbstractWrapper1、QueryWrapper UpdateWrapperQueryWrapper 在where条件的基础上可以控制多加了select 可选的查询字段。默认是select *1QueryWrapper 示例2updateWrapper示例UpdateWrapper第一个参数传null是因为你不提供实体对象如果你传了实体MP 会把实体中非空字段也加入 SET可能造成意料之外的覆盖。⚠️ 注意事项如果你有实体对象并且想更新它的某些字段 按主键更新也可以用User user new User(); user.setId(1001); user.setNickname(新昵称); userMapper.updateById(user); // 更简洁这种情况不需要UpdateWrapper。小结场景推荐方式按主键更新几个字段updateById(entity)按非主键条件更新update(null, updateWrapper)动态条件/字段更新UpdateWrapper或LambdaUpdateWrapper2、AbstractLambdaWrapper以上的queryWrapper 和 updateWrapper 字段名都是写死的硬编码。二、小结三、QueryWrapper VS UpdateWrapper3-1、一句话区分Wrapper用途核心能力QueryWrapper查询、删除只构造WHERE条件UpdateWrapper更新构造WHERE条件SET更新内容3-2、继承关系AbstractWrapper ← 所有 Wrapper 的基类构造 WHERE ├── QueryWrapper ← 只负责 WHERE ├── UpdateWrapper ← 负责 WHERE SET └── LambdaQueryWrapper / LambdaUpdateWrapper ← 各自对应的 Lambda 版本UpdateWrapper 比 QueryWrapper 多了一个set()方法用来指定要更新的字段和值。3-3、代码对比同一个业务场景场景把年龄大于 30 且状态为禁用的用户状态改为启用。❌ 错误用 QueryWrapper 做更新// QueryWrapper 只能构造 WHERE没法指定 SET 内容 QueryWrapperUser queryWrapper new QueryWrapper(); queryWrapper.gt(age, 30).eq(status, 0); // update() 方法需要传入一个实体对象作为 SET 内容 User user new User(); user.setStatus(1); // 要更新的字段值放在实体里 userMapper.update(user, queryWrapper);缺点实体user中其他字段如果为null配合not_null策略会被忽略但你得new一个对象逻辑上条件和更新内容分离不够直观✅ 正确用 UpdateWrapper 做更新UpdateWrapperUser updateWrapper new UpdateWrapper(); // WHERE 条件年龄 30 且 状态 0 updateWrapper.gt(age, 30).eq(status, 0); // SET 内容直接在这里指定 updateWrapper.set(status, 1); // 还可以同时更新多个字段 updateWrapper.set(update_time, new Date()); userMapper.update(null, updateWrapper);优点条件和更新内容写在一起一目了然第一个参数传null完全不需要 new 实体对象可以更新为nullset(phone, null)不受实体 null 策略影响3-4、什么时候用哪个决策树你要做什么操作 │ ├─→ 查询SELECT─────────────────→ QueryWrapper / LambdaQueryWrapper │ 例list(wrapper)、getOne(wrapper)、count(wrapper) │ ├─→ 删除DELETE─────────────────→ QueryWrapper / LambdaQueryWrapper │ 例remove(wrapper) │ 删除只需要条件不需要 SET │ └─→ 更新UPDATE─────────────────→ UpdateWrapper / LambdaUpdateWrapper 例update(null, wrapper) 更新既需要 WHERE 条件又需要 SET 内容3-5、Lambda 版本推荐实际使用上面用的是字符串硬编码列名容易写错。实际开发强烈推荐 Lambda 版本LambdaQueryWrapper —— 查询/删除// 查询名字包含张且状态启用的用户 LambdaQueryWrapperUser lqw new LambdaQueryWrapper(); lqw.like(User::getUsername, 张) .eq(User::getStatus, 1); ListUser list userMapper.selectList(lqw);LambdaUpdateWrapper —— 更新// 更新id1 的用户只改邮箱和更新时间 LambdaUpdateWrapperUser luw new LambdaUpdateWrapper(); luw.eq(User::getId, 1L) .set(User::getEmail, newqq.com) .set(User::getUpdateTime, new Date()); userMapper.update(null, luw);Lambda 的好处User::getUsername是编译期检查的列名写错直接编译报错不会等到运行时才暴露。3-6、一个完整的实战对比Service public class UserService { Autowired private UserMapper userMapper; // 查询用 QueryWrapper public ListUser getActiveUsersByAge(Integer minAge) { LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.ge(User::getAge, minAge) // WHERE age ? .eq(User::getStatus, 1); // AND status 1 return userMapper.selectList(wrapper); } // 删除用 QueryWrapper public boolean deleteInactiveUsers() { LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getStatus, 0) // WHERE status 0 .lt(User::getCreateTime, LocalDateTime.now().minusYears(1)); // AND create_time 一年前 return userMapper.delete(wrapper) 0; } // 更新用 UpdateWrapper public boolean banUsersByAge(Integer maxAge) { LambdaUpdateWrapperUser wrapper new LambdaUpdateWrapper(); wrapper.le(User::getAge, maxAge) // WHERE age ? .eq(User::getStatus, 1) // AND status 1 .set(User::getStatus, 0) // SET status 0 .set(User::getUpdateTime, LocalDateTime.now()); // SET update_time now() return userMapper.update(null, wrapper) 0; } }3-7、容易踩的坑坑说明UpdateWrapper 做查询语法上可行因为继承了 AbstractWrapper但语义不对别这么干QueryWrapper 做更新但没传实体update(null, queryWrapper)→ SET 子句为空SQL 报错UpdateWrapper 传了实体又用了 set()两者会合并实体和 set() 都会进 SET 子句注意别重复忘记update(null, wrapper)第一个参数用 UpdateWrapper 时第一个参数固定传null3-8、速记口诀查删用 Query更新用 Update。Query 只管 WHEREUpdate 还能 SET。