MyBatis-Plus实战:lambdaQuery与lambdaUpdate的10个高频使用场景(附代码示例)

MyBatis-Plus实战:lambdaQuery与lambdaUpdate的10个高频使用场景(附代码示例)

如果你已经用上了MyBatis-Plus,但每次写查询和更新时,还在和那些容易拼错的字段名字符串打交道,那这篇文章就是为你准备的。我见过不少团队,虽然引入了MP,但开发体验的提升却有限,问题往往出在对Lambda查询和更新这套“语法糖”的理解不够深入,用得不够“溜”。今天,我们就抛开那些基础概念,直接切入实际开发中最常遇到的十几个场景,看看如何用lambdaQuerylambdaUpdate写出更优雅、更安全、也更高效的代码。这不仅仅是语法展示,更是我踩过不少坑后总结出的最佳实践。

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判断,代码显得冗长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值