您好,登录后才能下订单哦!
# LambdaQueryWrapper多条件嵌套查询方法详解
## 1. 引言
在MyBatis-Plus框架中,`LambdaQueryWrapper`是一个强大的查询条件构造器,它允许开发者以Lambda表达式的方式构建类型安全的查询条件。相比传统的字符串拼接方式,`LambdaQueryWrapper`提供了更优雅、更安全的查询条件构建方法。本文将深入探讨`LambdaQueryWrapper`的多条件嵌套查询方法,帮助开发者掌握复杂查询场景下的使用技巧。
## 2. LambdaQueryWrapper基础
### 2.1 基本概念
`LambdaQueryWrapper`是MyBatis-Plus提供的一个查询条件包装器,它通过Lambda表达式引用实体类的属性,避免了硬编码字段名的风险。主要特点包括:
- 类型安全:编译时检查属性名是否正确
- 代码智能提示:IDE能提供属性名的自动补全
- 链式调用:支持流畅的API设计
### 2.2 基本使用方法
```java
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "张三")
.gt(User::getAge, 18)
.orderByDesc(User::getCreateTime);
List<User> users = userMapper.selectList(wrapper);
默认情况下,多个条件是通过AND连接的:
wrapper.eq(User::getDepartment, "研发部")
.ge(User::getSalary, 10000);
对应的SQL:WHERE department = '研发部' AND salary >= 10000
使用or()
方法可以实现OR条件连接:
wrapper.eq(User::getDepartment, "研发部")
.or()
.eq(User::getDepartment, "市场部");
对应的SQL:WHERE department = '研发部' OR department = '市场部'
当需要构建更复杂的条件时,可以使用嵌套查询。例如,查询年龄大于30或者(名字包含”张”并且工资小于5000)的员工:
wrapper.gt(User::getAge, 30)
.or(w -> w.like(User::getName, "张")
.lt(User::getSalary, 5000));
对应的SQL:WHERE age > 30 OR (name LIKE '%张%' AND salary < 5000)
同样可以嵌套OR条件:
wrapper.eq(User::getStatus, 1)
.and(w -> w.gt(User::getAge, 25)
.or()
.lt(User::getSalary, 8000));
对应的SQL:WHERE status = 1 AND (age > 25 OR salary < 8000)
可以构建更复杂的多级嵌套条件:
wrapper.and(w1 -> w1.eq(User::getType, 1)
.or()
.eq(User::getType, 2))
.or(w2 -> w2.like(User::getName, "admin")
.and(w3 -> w3.isNotNull(User::getEmail)
.eq(User::getStatus, 1)));
对应的SQL:
WHERE (type = 1 OR type = 2)
OR (name LIKE '%admin%' AND (email IS NOT NULL AND status = 1))
wrapper.and(w -> w.between(User::getAge, 20, 30)
.or()
.between(User::getAge, 40, 50));
wrapper.and(w -> w.like(User::getName, "张")
.or()
.like(User::getNickname, "张"));
wrapper.eq(User::getCompany, "ABC公司")
.and(w -> w.gt(User::getWorkYears, 3)
.or()
.eq(User::getEducation, "硕士"));
public List<User> queryUsers(String name, Integer minAge, Integer maxAge) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StringUtils.isNotBlank(name), User::getName, name)
.and(w -> w.ge(minAge != null, User::getAge, minAge)
.le(maxAge != null, User::getAge, maxAge));
return userMapper.selectList(wrapper);
}
wrapper.nested(w -> {
if (condition1) {
w.eq(User::getField1, value1);
}
if (condition2) {
w.or().eq(User::getField2, value2);
}
});
虽然嵌套查询很强大,但过度嵌套会导致SQL复杂,影响性能。建议: - 嵌套层级不超过3层 - 复杂的业务逻辑考虑拆分成多个查询
确保嵌套条件中的字段有适当的索引: - 等值查询字段优先 - 范围查询字段放在后面
将高选择性的条件放在前面,可以更快过滤数据:
wrapper.eq(User::getId, 123) // 高选择性条件
.and(w -> w.like(User::getName, "%张%"));
public List<User> advancedSearch(UserQuery query) {
return lambdaQuery()
.eq(query.getDeptId() != null, User::getDeptId, query.getDeptId())
.and(w -> w.like(StringUtils.isNotBlank(query.getKeyword()),
User::getName, query.getKeyword())
.or()
.like(StringUtils.isNotBlank(query.getKeyword()),
User::getMobile, query.getKeyword()))
.between(query.getStartTime() != null && query.getEndTime() != null,
User::getCreateTime, query.getStartTime(), query.getEndTime())
.orderByDesc(User::getCreateTime)
.list();
}
public List<Order> queryOrdersWithPermission(Long userId) {
return lambdaQuery()
.eq(Order::getStatus, 1)
.and(w -> w.eq(Order::getUserId, userId)
.or()
.inSql(Order::getDeptId,
"SELECT dept_id FROM user_dept WHERE user_id = " + userId))
.list();
}
可能原因: 1. 条件逻辑错误 2. 使用了错误的连接方式
解决方案:
// 错误示例
wrapper.or(w -> w.eq(User::getA, 1))
.eq(User::getB, 2); // 此条件会在OR之外
// 正确写法
wrapper.or(w -> w.eq(User::getA, 1)
.eq(User::getB, 2));
使用括号明确优先级:
wrapper.and(w -> w.eq(User::getA, 1)
.or()
.eq(User::getB, 2))
.eq(User::getC, 3);
使用nested
方法处理复杂动态条件:
wrapper.nested(w -> {
if (conditionA) {
w.eq(User::getA, 1);
}
if (conditionB) {
w.or().eq(User::getB, 2);
}
});
LambdaQueryWrapper
的多条件嵌套查询为复杂业务场景提供了强大的支持。通过本文的介绍,我们了解了:
掌握这些技巧后,开发者能够更加灵活地构建各种复杂查询,同时保持代码的类型安全和可维护性。在实际项目中,应根据具体业务需求合理选择查询构建方式,避免过度复杂的嵌套查询影响性能。
方法名 | 描述 | 示例 |
---|---|---|
eq |
等于 | eq(User::getName, "张三") |
ne |
不等于 | ne(User::getStatus, 0) |
gt |
大于 | gt(User::getAge, 18) |
ge |
大于等于 | ge(User::getScore, 60) |
lt |
小于 | lt(User::getSalary, 10000) |
le |
小于等于 | le(User::getLevel, 5) |
between |
介于 | between(User::getAge, 20, 30) |
like |
模糊匹配 | like(User::getName, "%张%") |
in |
IN查询 | in(User::getId, ids) |
and |
AND嵌套 | and(w -> w.eq(...)) |
or |
OR嵌套 | or(w -> w.eq(...)) |
nested |
复杂嵌套 | nested(w -> {...}) |
”`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。