在 Spring Boot 中,只要让 Service 实现类继承 MyBatis-Plus 提供的 ServiceImpl,就可以直接使用 lambdaQuery() 方法进行链式查询

核心前提:正确继承

要使用 lambdaQuery(),您的 Service 接口和实现类必须遵循以下继承规则:
Service 接口:需要继承 IService
Service 实现类:需要继承 ServiceImpl<M, T>,其中 M 是 Mapper 接口,T 是实体类。

@Service
public class SysUserServiceImpl 
    extends ServiceImpl<SysUserMapper, SysUser> 
    implements ISysUserService {
    // 继承后,自动拥有 lambdaQuery()、list()、getById() 等方法
}

lambdaQuery() 的使用方式

  • 动态条件查询列表(支持条件判断,类似 MyBatis 的 标签)
List<SysUser> users = this.lambdaQuery()
    // 当 userName 不为空时,才拼接 like 条件
    .like(StringUtils.isNotBlank(userName), SysUser::getUserName, userName)
    // 当 status 不为空时,才拼接 eq 条件
    .eq(StringUtils.isNotBlank(status), SysUser::getStatus, status)
    .list(); // 最后调用 list() 执行查询
  • 查询单条记录
SysUser user = this.lambdaQuery()
    .eq(SysUser::getId, userId)
    .one(); // 调用 one() 获取单条记录
  • 查询数量:
Long count = this.lambdaQuery()
    .eq(SysUser::getStatus, "1")
    .count(); // 调用 count() 获取数量

在 MyBatis-Plus 中,this.lambdaQuery() 返回的是一个 LambdaQueryChainWrapper 对象。在这个链式调用中,你可以拼接的方法主要分为三大类:

1. 条件构造方法(中间拼接)

这类方法用于动态组装 SQL 的 WHERE 子句。它们支持 Lambda 表达式(如 Entity::getField),并且通常支持传入一个 boolean 类型的条件参数,只有当条件为 true 时,该 SQL 片段才会被拼接到最终语句中。
等值与不等值:eq (等于), ne (不等于)
大小比较:gt (大于), ge (大于等于), lt (小于), le (小于等于)
模糊查询:like (包含), likeLeft (右模糊), likeRight (左模糊), notLike
范围查询:between, notBetween
包含查询:in, notIn
空值判断:isNull, isNotNull
逻辑嵌套:and (AND 嵌套), or (OR 嵌套)
其他:orderByDesc (降序), orderByAsc (升序), select (指定查询列) 等

2. 结果集获取方法(链式结尾)

这是链式调用的终结方法。MyBatis-Plus 会根据你最后调用的这个方法,来决定执行什么类型的 SQL 以及返回什么格式的数据:
.one():获取单条记录。如果查询到多条记录,会抛出 TooManyResultsException 异常。
.list():获取列表数据,返回 List 集合。
.count():获取统计数量,返回 Long 或 Integer。
.page(IPage page):进行分页查询,返回分页对象(需传入分页参数)。
.getWrapper():获取当前链式构建的底层 LambdaQueryWrapper 对象(适用于需要将条件传递给其他复杂方法的场景)。

3. 实体注入方法

例子:
场景一:动态条件查询列表

List<User> users = this.lambdaQuery()
    // 只有当 username 不为空时,才拼接 like 条件
    .like(StringUtils.isNotBlank(username), User::getUsername, username)
    // 只有当 status 不为空时,才拼接 eq 条件
    .eq(status != null, User::getStatus, status)
    // 以 list() 结尾,返回集合
    .list(); 

场景二:查询单条并排序

User user = this.lambdaQuery()
    .eq(User::getPhone, "13800138000")
    .orderByDesc(User::getCreateTime) // 按创建时间倒序
    .one(); // 以 one() 结尾,返回单条记录

场景三:获取底层 Wrapper

// 获取构建好的 Wrapper,用于传给其他方法
LambdaQueryWrapper<User> wrapper = this.lambdaQuery()
    .eq(User::getStatus, 1)
    .getWrapper(); 

.setEntity(entity):可以将一个实体对象传入,MyBatis-Plus 会将该实体中非空的属性默认作为 eq (等于) 的查询条件拼接到 SQL 中。

LambdaQueryWrapper

除了 lambdaQuery() 链式调用,您也可以单独创建 LambdaQueryWrapper,然后传给 Service 或 Mapper 的方法中,效果是一样的:

LambdaQueryWrapper 是 MyBatis-Plus 框架中提供的一个非常核心的查询条件构造器。它基于 Java 8 的 Lambda 表达式特性,允许开发者通过实体类的属性引用来构建 SQL 的 WHERE 查询条件,从而完全替代手写 SQL 或传统的字符串拼接方式。

// 创建 Wrapper
LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
wrapper.like(SysUser::getUserName, "admin");

// 方式一:在 Service 层使用
List<SysUser> list1 = this.list(wrapper);

// 方式二:在 Mapper 层使用
List<SysUser> list2 = this.baseMapper.selectList(wrapper);
方法说明示例
eq(字段, 值)等于 =.eq(User::getId, 1)
ne(字段, 值)不等于 !=.ne(User::getStatus, 0)
gt(字段, 值)大于 >.gt(User::getAge, 18)
ge(字段, 值)大于等于 >=.ge(User::getAge, 18)
lt(字段, 值)小于 <.lt(User::getAge, 60)
le(字段, 值)小于等于 <=.le(User::getAge, 60)
like(字段, 值)模糊匹配 LIKE '%值%'.like(User::getName, "张")
likeLeft(字段, 值)左模糊 LIKE '%值'.likeLeft(User::getName, "三")
likeRight(字段, 值)右模糊 LIKE '值%'.likeRight(User::getName, "张")
in(字段, 集合)IN 查询.in(User::getId, Arrays.asList(1,2,3))
isNull(字段)为 NULL.isNull(User::getEmail)
isNotNull(字段)不为 NULL.isNotNull(User::getEmail)
orderByAsc(字段)升序.orderByAsc(User::getAge)
orderByDesc(字段)降序.orderByDesc(User::getCreateTime)
between(字段, 值1, 值2)区间查询.between(User::getAge, 18, 60)
and(条件)嵌套 AND.and(w -> w.gt(User::getAge, 18).lt(User::getAge, 60))
or()OR.eq(User::getId, 1).or().eq(User::getId, 2)
select(字段...)指定查询列.select(User::getId, User::getName)

总结来说,继承 ServiceImpl 后,无论是使用 this.lambdaQuery().eq(…).list() 的链式写法,还是 this.list(wrapper) 的传参写法,都能极大简化单表 CRUD 的代码量,并提升重构时的安全性。

注意事项

  • 适用场景:LambdaQueryWrapper 主要用于单表的复杂动态查询。如果涉及多表关联查询,通常还需要结合 MyBatis 的 XML 或自定义 SQL 来实现。
  • 安全性:使用 Lambda 表达式可以有效避免 SQL 注入风险,但在使用某些允许传入 SQL 片段的方法(如 last() 或 inSql())时,仍需注意防范安全漏洞。

更多推荐