MyBatis-Plus?中?nested()?與?and()?方法詳解(最佳實踐場景)
MyBatis-Plus 中nested()與and()方法詳解
在 MyBatis-Plus 的條件構(gòu)造器中,nested() 和 and() 都是用于構(gòu)建復雜查詢條件的關鍵方法,但它們在功能和使用場景上有顯著差異。
一、核心區(qū)別對比
| 特性 | and() | nested() |
|---|---|---|
| 主要用途 | 連接多個條件(默認AND) | 創(chuàng)建嵌套查詢條件 |
| 括號生成 | ? 不生成括號 | ? 自動生成括號包裹內(nèi)部條件 |
| 邏輯關系 | 與外部條件默認AND連接 | 可作為獨立邏輯單元 |
| 復雜查詢支持 | 有限,適合簡單條件組合 | 強大,支持任意層級嵌套 |
| OR 條件處理 | 需要顯式使用or() | 天然支持OR條件嵌套 |
| SQL 表現(xiàn) | 平鋪條件 | 生成帶括號的子表達式 |
二、方法詳解
1.and()方法
- 功能:連接多個查詢條件,默認使用 AND 邏輯
- 特點:
- 不會生成括號
- 適用于簡單的條件組合
- 當需要 OR 邏輯時需顯式調(diào)用
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()方法
- 功能:創(chuàng)建嵌套查詢條件(自動添加括號)
- 特點:
- 自動生成括號包裹內(nèi)部條件
- 支持任意層級的復雜嵌套
- 特別適合處理 OR 邏輯組合
- 使SQL邏輯更清晰
使用示例:
// 查詢(年齡>30 或 工資>10000) 且 狀態(tài)為激活的用戶
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() 實現(xiàn):
wrapper.and(wq -> wq.gt("age", 30).or().gt("salary", 10000))
.eq("status", 1);-- 邏輯錯誤!實際生成: WHERE (age > 30 OR salary > 10000 AND status = 1) -- 正確應使用括號包裹OR條件
使用 nested() 實現(xiàn):
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()當:
- 構(gòu)建簡單的 AND 條件組合
- 不需要改變條件優(yōu)先級
- 查詢條件邏輯簡單平鋪
使用nested()當:
- 需要處理 OR 條件組合
- 需要改變條件運算優(yōu)先級
- 構(gòu)建復雜嵌套查詢
- 需要清晰分隔邏輯單元
- 處理多條件分支邏輯
混合使用示例:
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()實現(xiàn)原理
public Children and(Consumer<Param> consumer) {
return addNestedCondition(true, consumer);
}- 內(nèi)部調(diào)用
addNestedCondition - 參數(shù)
true表示使用 AND 連接 - 不添加括號
2.nested()實現(xiàn)原理
public Children nested(Consumer<Param> consumer) {
return addNestedCondition(false, consumer);
}- 參數(shù)
false表示不指定連接類型 - 自動添加括號包裹表達式
- 可作為獨立邏輯單元嵌入
六、常見誤區(qū)
錯誤認為
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));忽略條件優(yōu)先級
// 錯誤:AND/OR優(yōu)先級問題 wrapper.eq("status", 1) .or() .eq("deleted", 0) .eq("name", "test"); // 正確:使用nested明確優(yōu)先級 wrapper.nested(nq -> nq.eq("status", 1).or().eq("deleted", 0)) .eq("name", "test");
七、性能考慮
數(shù)據(jù)庫優(yōu)化:
- 嵌套條件可能影響查詢優(yōu)化器的工作
- 避免超過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) // 索引列 );
總結(jié)
| 場景 | 推薦方法 |
|---|---|
| 簡單AND條件組合 | and() |
| OR條件組合 | nested() |
| 改變條件優(yōu)先級 | nested() |
| 多層級復雜查詢 | nested() |
| 邏輯單元清晰分隔 | nested() |
經(jīng)驗法則:
當需要括號來明確查詢邏輯時,總是使用
nested();
當只是簡單添加AND條件時,使用and()。
正確使用這兩個方法可以使你的MyBatis-Plus查詢:
- 邏輯更清晰
- 優(yōu)先級更明確
- 更易維護
- 充分利用數(shù)據(jù)庫優(yōu)化能力
- 避免難以調(diào)試的邏輯錯誤
到此這篇關于MyBatis-Plus 中 nested() 與 and() 方法詳解的文章就介紹到這了,更多相關MyBatis-Plus nested() 與 and() 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- 使用lombok注解導致mybatis-plus TypeHandler失效的解決
- 解決Mybatis-plus自定義TypeHandler查詢映射結(jié)果一直為null問題
- MyBatis-Plus中MetaObjectHandler沒生效完美解決
- mybatis-plus之自動映射字段(typeHandler)的注意點及說明
- Mybatis-Plus中and()和or()的使用與原理詳解
- MyBatis-Plus如何通過注解使用TypeHandler
- mybatis-plus如何配置自定義數(shù)據(jù)類型TypeHandle
- mybatis-plus QueryWrapper and or 連用并且實現(xiàn)分頁
- Mybatis-plus使用TableNameHandler分表詳解(附完整示例源碼)
相關文章
SpringBoot?LocalDateTime格式轉(zhuǎn)換方案詳解(前端入?yún)?
這篇文章主要介紹了SpringBoot?LocalDateTime格式轉(zhuǎn)換(前端入?yún)?,本文用示例介紹SpringBoot全局格式配置,將前端傳過來的時間自動轉(zhuǎn)化為LocalDateTime,需要的朋友可以參考下2023-04-04
java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼)
為避免繁瑣的注冊登陸,很多平臺和網(wǎng)站都會實現(xiàn)三方登陸的功能,增強用戶的粘性。這篇文章主要介紹了java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼),避免做微信登錄開發(fā)的朋友們少走彎路2022-12-12
MyBatis-Plus 主鍵生成策略的幾種實現(xiàn)方式
主鍵生成策略是指在數(shù)據(jù)庫中為每條記錄生成唯一標識符的方法,本文就來介紹一下MyBatis-Plus 主鍵生成策略的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-05-05
@scope("prototype") @loadbalanced注解負載均衡失效問題
這篇文章主要為大家介紹了@scope("prototype") @loadbalanced注解負載均衡失效問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
java出現(xiàn)no XXX in java.library.path的解決及eclipse配
這篇文章主要介紹了java出現(xiàn)no XXX in java.library.path的解決及eclipse配置方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

