QueryWrapper中or的使用技巧分享
場景描述
假設(shè)我們正在開發(fā)一個郵件系統(tǒng),系統(tǒng)中有一個名為 MailInfo 的表,用于存儲郵件信息。該表有兩個字段與用戶相關(guān):user_id 表示郵件的發(fā)送者,to_user_id 表示郵件的接收者。我們需要編寫一個查詢,找出當(dāng)前用戶(userId)所有與其相關(guān)的郵件,不論是他發(fā)送的,還是接收到的。此外,我們還要確保這些郵件未被刪除,并且按更新時間進行排序。
需求拆解
根據(jù)上述需求,我們需要實現(xiàn)以下幾點:
- 過濾掉已刪除的郵件(即 is_delete = 0)。
- 查詢條件包括 user_id 或 to_user_id 等于當(dāng)前用戶 ID。
- 按照更新時間(update_time)降序排序結(jié)果,以確保最新的郵件顯示在前面。
這些需求在 SQL 中可以通過一個簡單的 SELECT 語句來實現(xiàn),類似于:
SELECT * FROM MailInfo WHERE is_delete = 0 AND (user_id = ? OR to_user_id = ?) ORDER BY update_time DESC;
但在 Java 開發(fā)中,尤其是使用了 MyBatis-Plus 這樣一個 ORM 框架時,我們通常會使用 QueryWrapper
來構(gòu)造查詢條件,以提高代碼的可讀性和可維護性。
使用 MyBatis-Plus 構(gòu)建查詢條件
在 MyBatis-Plus 中,QueryWrapper 是一個非常強大的查詢構(gòu)造器,它可以通過流式 API 來動態(tài)地構(gòu)造 SQL 查詢。在處理復(fù)雜查詢條件時,例如 OR 和 AND 的組合,它也提供了相應(yīng)的接口來滿足需求。
下面我們來看一個具體的代碼示例,展示如何通過 QueryWrapper 來構(gòu)建我們的查詢條件:
Page<MailInfo> pageParm = new Page<>(); pageParm.setCurrent(page); pageParm.setSize(pageSize); QueryWrapper<MailInfo> wrapper = new QueryWrapper<>(); wrapper.eq("is_delete", 0) // 只查詢未刪除的郵件 .and(w -> w.eq("user_id", userId).or().eq("to_user_id", userId)) // 查詢當(dāng)前用戶發(fā)送或接收的郵件 .orderByDesc("update_time"); // 按更新時間降序排序 return Result.ok(MailInfoDTO.Converter.INSTANCE.from(this.mailInfoService.page(pageParm, wrapper)));
代碼解析
1. 分頁參數(shù)
Page<MailInfo> pageParm = new Page<>(); pageParm.setCurrent(page); pageParm.setSize(pageSize);
在大多數(shù)業(yè)務(wù)場景中,我們會對查詢結(jié)果進行分頁處理,以避免一次性返回過多數(shù)據(jù),影響性能。MyBatis-Plus 提供了 Page 類來處理分頁邏輯。在這段代碼中,我們通過 setCurrent 方法設(shè)置當(dāng)前頁數(shù),并通過 setSize 設(shè)置每頁返回的記錄數(shù)量。
2. 構(gòu)造查詢條件
QueryWrapper<MailInfo> wrapper = new QueryWrapper<>(); wrapper.eq("is_delete", 0) .and(w -> w.eq("user_id", userId).or().eq("to_user_id", userId));
這里的 QueryWrapper
是 MyBatis-Plus 提供的查詢構(gòu)造器,允許我們通過流式的方式來構(gòu)造查詢條件。
eq("is_delete", 0)
:添加一個is_delete = 0
的條件,確保只查詢未被標(biāo)記為刪除的郵件。and(w -> w.eq("user_id", userId).or().eq("to_user_id", userId))
:這是查詢條件的核心部分。我們通過and
方法組合多個條件,使用 Lambda 表達式w
作為內(nèi)部查詢條件的參數(shù)。在 Lambda 表達式內(nèi)部,先通過eq("user_id", userId)
查詢發(fā)送者為當(dāng)前用戶的郵件,再通過or().eq("to_user_id", userId)
查詢接收者為當(dāng)前用戶的郵件。通過這種方式,查詢結(jié)果將包含所有與當(dāng)前用戶相關(guān)的郵件記錄。
3. 排序條件
wrapper.orderByDesc("update_time");
這行代碼用于指定排序條件。我們希望按郵件的更新時間從新到舊進行排序,因此使用了 orderByDesc
方法,并將 update_time
作為排序字段。
結(jié)果封裝
在實際的開發(fā)過程中,我們通常會將查詢結(jié)果封裝為一個統(tǒng)一的返回結(jié)構(gòu)。在這個例子中,我們將查詢結(jié)果封裝為 Result.ok,并通過 MailInfoDTO.Converter.INSTANCE 進行數(shù)據(jù)轉(zhuǎn)換,將數(shù)據(jù)庫實體類 MailInfo 轉(zhuǎn)換為 MailInfoDTO。
QueryWrapper 的 or 使用技巧
在使用 QueryWrapper
構(gòu)建查詢時,or
方法是一個非常有用的工具。它允許我們在查詢中添加多個可能的條件,從而使查詢結(jié)果更加靈活。在本文的例子中,我們使用了 or
來查詢 user_id
或 to_user_id
等于 userId
的記錄,從而滿足了業(yè)務(wù)需求。
但是,使用 or
也需要小心,因為它可能會影響查詢的性能。在涉及大量數(shù)據(jù)時,OR
條件的查詢速度可能會較慢。為此,我們可以考慮以下優(yōu)化策略:
- 創(chuàng)建索引:確保
user_id
和to_user_id
字段上創(chuàng)建了索引,這樣可以大幅提高查詢速度。 - 使用緩存:在高頻率訪問的場景下,適當(dāng)?shù)厥褂镁彺婵梢詼p少數(shù)據(jù)庫查詢次數(shù),提升系統(tǒng)的整體性能。
- 分表設(shè)計:如果
MailInfo
表的數(shù)據(jù)量非常大,可以考慮通過分表來降低單個表的查詢壓力。
到此這篇關(guān)于QueryWrapper中or的使用技巧分享的文章就介紹到這了,更多相關(guān)QueryWrapper or使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java動態(tài)規(guī)劃之硬幣找零問題實現(xiàn)示例
本文主要介紹了Java動態(tài)規(guī)劃之硬幣找零問題實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08SpringBoot配置連接兩個或多個數(shù)據(jù)庫的實現(xiàn)
本文主要介紹了SpringBoot配置連接兩個或多個數(shù)據(jù)庫的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05SpringCloud之Zuul網(wǎng)關(guān)原理及其配置講解
這篇文章主要介紹了SpringCloud之Zuul網(wǎng)關(guān)原理及其配置講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03spring?IOC容器管理必須知道的一些操作(基于XML方式)
Spring框架的核心是Spring容器,容器創(chuàng)建對象,將它們裝配在一起,配置它們并管理它們的完整生命周期,下面這篇文章主要給大家介紹了關(guān)于spring?IOC容器管理必須知道的一些操作,需要的朋友可以參考下2022-03-03