MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)
目录
- MyBATis-Plus 中nested()与and()方法详解
- 一、核心区别对比
- 二、方法详解
- 1.and()方法
- 2.nested()方法
- 三、高级用法对比
- 1. 复杂 OR 条件处理
- 2. 多层级嵌套
- 四、最佳实践场景
- 使用and()当:
- 使用nested()当:
- 混合使用示例:
- 五、原理分析
- 1.and()实现原理
- 2.nested()实现原理
- 六、常见误区
- 七、性能考虑
- 总结
MyBatis-Plus 中nested()与and()方法详解
在 MyBatis-Plus 的条件构造器中,nested() 和 and() 都是用于构建复杂查询条件的关键方法,但它们在功能和使用场景上有显著差异。
一、核心区别对比
| 特性 | and() | nested() |
|---|---|---|
| 主要用途 | 连接多个条件(默认AND) | 创建嵌套查询条件 |
| 括号生成 | ❌ 不生成括号 | ✅ 自动生成括号包裹内部条件 |
| 逻辑关系 | 与外部条件默认AND连接 | 可作为独立逻辑单元 |
| 复杂查询支持 | 有限,适合简单条件组合 | 强大,支持任意层级嵌套 |
| OR 条件处理 | 需要显式使用or() | 天然支持OR条件嵌套 |
| SQL 表现 | 平铺条件 | 生成带括号的子表达式 |
二、方法详解
1.and()方法
- 功能:连接多个查询条件,默认使用 AND 逻辑
- 特点:
- 不会生成括号
- 适用于简单的条件组合
- 当需要 OR 逻辑时需显式调用
or()
使用示例:
// 查询年龄大于18且姓张的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
.and(wq -> wq.like("name", "张"));
生成 SQL:
WHERE age > 18 AND name LIKE '%张%'
2.nested()方法
- 功能:创建嵌套查询条件(自动添加括号)
- 特点:
- 自动生成括号包裹内部条件
- 支持任意层级的复杂嵌套
- 特别适合处理 OR 逻辑组合
- 使SQL逻辑更清晰
使用示例:
// 查询(年龄>30 或 工资>10000) 且 状态为激活的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.nested(nq ->
nq.gt("age", 30).or().gt("salary", 10000))
.eq("status", 1);
生成 SQL:
WHERE (age > 30 OR salary > 10000) AND status = 1
三、高级用法对比
1. 复杂 OR 条件处理
使用 and() 实现:
wrapper.and(wq -> wq.gt("age", 30).or().gt("salary", 10编程客栈000))
.eq("status", 1);
-- 逻辑错误!实际生成: WHERE (age > 30 OR salary > 10000 AND status = 1) -- 正确应使用括号包裹OR条件
使用 nested() 实现:
wrapper.nested(nq -> nq.gt("age", 30).or().gt("salary", 10000))
.eq("status", 1);
-- 正确生成: WHERE (age > 30 OR salary > 10000) AND status = 1
2. 多层级嵌套
nested() 支持无限嵌套:
wrapper.nested(nq1 ->
nq1.eq("type", 1)
.nested(nq2 ->
nq2.lt("age", 20).or().gt("age", 60))
)
.like("name", "张");
生成 SQL:
WHERE (type = 1 AND (age < 20 OR age > 60)) AND name LIKE '%张%'
四、最佳实践场景
使用and()当:
- 构建简单的 AND 条件组合
- 不需要改变条件优先级
- 查询条件逻辑简单平铺
使用nested()当:
- 需要处理 OR 条件组合
- 需要改变条件运算优先级
- 构建复杂嵌套查询
- 需要清晰分隔逻辑单元
- 处理多条件分支逻辑
混合使用示例:
wrapper.eq("dept_id", 10)
.nested(nq ->
nq.like("name", "张")
.or()
.nested(nq2 ->
nq2.gt("salary", 10000).lt("age", 40))
);
生成 SQL:
WHERE dept_id = 10 AND (name LIKE '%张%' OR (salary > 10000 AND age < 40))
五、原理分析
1.and()实现原理
public Children and(Consumer<Param> consumer) {
return addNestedCondition(true, consumer);
}
- 内部调用
addNestedCondition - 参数
true表示使用 AND 连接 - 不添加括号
2.nested()实现原理
public Children nested(Consumer<Param> consumer) {
return addNestedCondition(false, consumer);
}
- 参数
fa编程客栈lse表示不指定连接类型 - 自动添加括号包裹表达式
- 可作为独立逻辑单元嵌入
六、常见误区
错误认为
and()会加括号- ✅ 只有
nested()会生成括号
- ✅ 只有
在 OR 条件中错误使用
and()// 错误:OR条件未正确包裹 wrapper.eq("a", 1) .or() .and(wq -> wq.eq("b", 2).eq("c", 3)); // 正确:使用nested wrapper.eq("a", 1) .or() .nested(nq -> nq.eq("b", 2).eq("c", 3));忽略条件优先级
// 错误:AND/OR优先级问题 wrapper.eq("status", 1) .or() .eq("deleted", 0) .eq("name", "test"); // 正确:使用nested明确优先级 wrapper.nested(nq -> nq.eq("status", 1).or().eq("deleted", 0)) .eq("name", "test");
七、性能考虑
数据库优化:
- 嵌套条件可能影响查询优化器的工作
- 避免超过3层嵌套(影响可读性和性能)
索引利用:
// 好的实践:索引列前置 wrapper.nested(nq -> nq.eq("indexed_column1", val1) // 索引列 .or() .eq("indexed_column2", val2) // 索引列 ); // 避免:非索引列前置 wrapper.nested(nq -> nq.eq("non_indexed", val) // 非索引列 .or() .eq("indexed_column", val) // 索引列 );
总结
| 场景 | 推荐方法 |
|---|---|
| 简单AND条件组合 | and() |
| OR条件组合 | nested() |
| 改变条件优先级 | nested() |
| 多层级复杂查询 | nested() |
| 逻辑单元清晰分隔 | nested()lgCKoXa |
经验法则:
当需要括号来明确查询逻辑时,总是使用
当只是简单添加lgCKoXaAND条件时,使用nested();and()。
正确使用这两个方法可以使你的MyBatis-Plus查询:
- 逻辑更清晰
- 优先级更明确
- 更易维护
- 充分利用数据库优化能力
- 避免难以调试的逻辑错误
到此这篇关于MyBatis-Plus 中 nested() 与 and() 方法详解的文章就介绍到这了,更多相关MyBatis-Plus nested() 与 and() 内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.cppcnphps.com)!
加载中,请稍侯......
精彩评论