MyBatis-Plus实战:lambdaQuery与lambdaUpdate的10个高频使用场景(附代码示例)
如果你已经用上了MyBatis-Plus,但每次写查询和更新时,还在和那些容易拼错的字段名字符串打交道,那这篇文章就是为你准备的。我见过不少团队,虽然引入了MP,但开发体验的提升却有限,问题往往出在对Lambda查询和更新这套“语法糖”的理解不够深入,用得不够“溜”。今天,我们就抛开那些基础概念,直接切入实际开发中最常遇到的十几个场景,看看如何用lambdaQuery和lambdaUpdate写出更优雅、更安全、也更高效的代码。这不仅仅是语法展示,更是我踩过不少坑后总结出的最佳实践。
1. 基础查询:从“字符串”到“类型安全”的飞跃
在MyBatis-Plus的早期版本,或者在不熟悉Lambda特性的开发者手中,我们经常看到这样的代码:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", "张三").eq("deleted", 0);
List<User> userList = userMapper.selectList(queryWrapper);
这段代码的问题显而易见:"user_name"和"deleted"是字符串,一旦数据库字段名变更,或者手滑打错字,编译器不会给你任何提示,错误只有在运行时才会暴露,通常是令人头疼的查询结果为空或者报错。而lambdaQuery的出现,彻底解决了这个问题。
它的核心优势在于将字段引用从字符串提升为Lambda方法引用,实现了编译期的类型安全检查。 让我们重构上面的例子:
List<User> userList = userService.lambdaQuery()
.eq(User::getUserName, "张三")
.eq(User::getDeleted, 0)
.list();
这里,User::getUserName是一个SFunction类型的Lambda表达式,它指向的是User实体类的getUserName()方法。编译器会检查这个方法是否存在,如果字段名后续从user_name改为username,你只需要修改实体类的属性名和对应的getter方法名,所有使用User::getUserName的地方都会在编译时报错,迫使你同步更新,这极大地提升了代码的健壮性和可维护性。
提示:
lambdaQuery()方法返回的是一个LambdaQueryWrapper<T>对象,它继承了AbstractLambdaWrapper,内部通过SerializedLambda和缓存机制,将方法引用解析为对应的数据库字段名,性能开销在可接受范围内。
1.1 多条件组合查询:and与or的灵活运用
实际业务中,单一条件查询很少见,更多的是多条件的灵活组合。lambdaQuery提供了清晰的链式调用API来构建复杂条件。
场景一:并列条件(AND) 查询年龄大于18岁且状态为激活的用户,这是最常见的AND关系。
List<User> list = userService.lambdaQuery()
.gt(User::getAge, 18)
.eq(User::getStatus, 1) // 假设1代表激活状态
.list();
链式调用的多个.eq(), .gt()等条件默认以AND连接。
场景二:嵌套或条件(OR) 查询名字是“张三”或者“李四”的用户。这里需要用到.or()方法。
List<User> list = userService.lambdaQuery()
.eq(User::getName, "张三")
.or()
.eq(User::getName, "李四")
.list();
生成的SQL类似于:WHERE name = '张三' OR name = '李四'
场景三:复杂的条件分组 这是一个更复杂的场景:查询(状态为激活且年龄大于20)或者(状态为未激活且注册时间在一年以内)的用户。这需要用到条件括号。
List<User> list = userService.lambdaQuery()
.and(wq -> wq.eq(User::getStatus, 1).gt(User::getAge, 20))
.or(wq -> wq.eq(User::getStatus, 0).ge(User::getCreateTime, LocalDateTime.now().minusYears(1)))
.list();
生成的SQL类似于:WHERE (status = 1 AND age > 20) OR (status = 0 AND create_time >= '2023-05-01') .and()和.or()方法接受一个Consumer函数,用于构建一个子条件组,天然地形成了SQL中的括号,让复杂逻辑的表达变得直观。
2. 动态查询:告别繁琐的if判断
业务查询条件经常是动态的,例如前端传过来的搜索参数,可能为空,也可能有值。传统写法需要写大量的if判断,代码显得冗长。

&spm=1001.2101.3001.5002&articleId=153096162&d=1&t=3&u=aed3be3b937c4e639d18fe55f1abab90)
487

被折叠的 条评论
为什么被折叠?



