作為一名 Java 開發(fā)者,你一定經(jīng)歷過被 MyBatis XML 支配的恐懼。
當(dāng)你打開一個(gè) UserMapper.xml,迎面而來的是幾百行甚至上千行的 , , , 標(biāo)簽。原本清爽的 SQL 語句被這些 XML 標(biāo)簽切割得支離破碎,仿佛老太太的裹腳布——又臭又長。
如果你也受夠了在 XML 標(biāo)簽里寫邏輯,受夠了為了一個(gè)簡單的非空判斷就要寫三行 XML,那么請繼續(xù)往下看。dbVisitor 的動(dòng)態(tài) SQL 規(guī)則機(jī)制,也許就是你一直在尋找的 "剪刀"。
MyBatis 的 XML 地獄
讓我們先回顧一下,一個(gè)標(biāo)準(zhǔn)的、帶有幾個(gè)查詢條件的 MyBatis SQL 是什么樣子的:
這段代碼的問題在哪里,已經(jīng)不用多言!這種 一坨一坨 的開發(fā)體驗(yàn)看到就難受至極,更別提還要去維護(hù)它。
革命性的解法
dbVisitor 作為一個(gè)新一代的數(shù)據(jù)庫訪問工具,最核心的設(shè)計(jì)理念之一就是:讓 SQL 回歸 SQL。
利用 dbVisitor 獨(dú)創(chuàng)的 規(guī)則機(jī)制,上面的 XML 代碼可以精簡為:
@{and, create_time >= :createTime}假設(shè)只傳入?yún)?shù) name="Tom",生成的 SQL 如下:
SELECT * FROM tb_user WHERE name = ?是不是瞬間清爽了?沒有了尖括號(hào)的視覺干擾,沒有了冗余的 XML 閉合標(biāo)簽,只有純粹的 SQL 邏輯。
你可能會(huì)問:@{and, ...} 到底做了什么?它是簡單的字符串拼接嗎?
當(dāng)然不是!dbVisitor 的規(guī)則是非常智能的,以 @{and, name = :name} 為例,它內(nèi)置了以下邏輯:
智能判空
引擎會(huì)自動(dòng)檢查 key = :key 表達(dá)式中的參數(shù)。如果參數(shù) :key 為 null,整個(gè) @{and} 規(guī)則塊會(huì)被自動(dòng)忽略,不會(huì)生成任何 SQL。
(注意:空字符串""被視為有效值,不會(huì)忽略)
WHERE 處理
如果內(nèi)容不為空 @{and} 會(huì)識(shí)別它是否是 WHERE 子句的開頭。如果是開頭(例如前面沒有1=1),它會(huì)自動(dòng)抹去 AND,直接生成 WHERE name = ?
(這一點(diǎn)類似 MyBatis 的標(biāo)簽,但更加隱形)
這一切都是自動(dòng)發(fā)生的,你只需要聲明規(guī)則,剩下的交給 dbVisitor。
條件判斷本該如此性感
MyBatis 中 90% 的 標(biāo)簽都是為了做兩件事:
參數(shù)不為空時(shí),追加查詢條件。
開關(guān)開啟時(shí),追加查詢條件。
dbVisitor 將這兩類高頻場景直接內(nèi)化為最基礎(chǔ)的規(guī)則,無需任何復(fù)雜的標(biāo)簽嵌套。
智能補(bǔ)全
自動(dòng)檢查條件狀態(tài)選擇是否需要自動(dòng)補(bǔ)全 WHERE/AND/OR 關(guān)鍵字。
@{and, name = :name} -- 生成 and name = ?2. 智能判空
@{and} 和 @{or} 這是最常用的判空規(guī)則,它們會(huì)自動(dòng)檢查參數(shù)是否為 null。
@{or, age > :age} -- 僅當(dāng) age 不為空時(shí)生成 or age > ?3. 開關(guān)控制
@{ifand} 和 @{ifor} 當(dāng)你需要用布爾值來控制 SQL 時(shí)就會(huì)使用他們。
SELECT * FROM tb_user @{ifand, !showAll, is_delete = 0}對比 MyBatis 的臃腫寫法以及像老鼠屎一樣無處不在的 1=1
僅僅是一個(gè)簡單的條件,dbVisitor 讓你少寫了 3 行代碼,減少無用的條件判斷,這就是效率。
一行代碼的 IN 查詢
MyBatis 的 標(biāo)簽簡直是反人類設(shè)計(jì):collection, item, open, close... 配置項(xiàng)多達(dá)七八個(gè),而且為了防止集合為空導(dǎo)致 SQL 語法錯(cuò)誤,通常還得在外面套一層,簡直令人窒息:
if>而在 dbVisitor 中,利用 @{ifand} 和 @{in} 兩個(gè)規(guī)則的 嵌套使用,你只需要一行:
@{ifand, !idList.isEmpty, id IN @{in, :idList}}對比一下,這代碼量節(jié)省的可不是一點(diǎn)點(diǎn),而是 降維打擊!
忘掉 , 忘掉逗號(hào)
在寫 Update 語句時(shí),處理末尾的逗號(hào)是最煩人的。dbVisitor 的 @{set}規(guī)則完美解決,引擎會(huì)自動(dòng)處理字段間的逗號(hào):
WHERE id = #{id}MyBatis 用了一大堆標(biāo)簽來解決這個(gè)問題:
WHERE id = #{id}?? 雖然 @{set} 規(guī)則很強(qiáng)大,但規(guī)則的判斷是依賴已經(jīng)生成的 SQL 進(jìn)行推斷。
當(dāng)規(guī)則沒有匹配時(shí),一些意外情況:
WHERE id = :id分支判斷的救星
MyBatis 的 - - 結(jié)構(gòu)冗長得令人發(fā)指,寫起來仿佛在填表。最大的麻煩在于即便是使用 @Select 注解仍然逃脫不了 XML 的魔咒。
@Param("content") String content);dbVisitor 讓你用 SQL 的思維寫 SQL,更符合編程直覺。同樣的場景,dbVisitor 只需要這樣:
CASE 規(guī)則 IF-ELSE 模式
}CASE 規(guī)則 Switch 模式 換一個(gè)例子:根據(jù) encryptMode 的值選擇加密方式。
}像樂高積木一樣組合
規(guī)則引擎最強(qiáng)大的地方在于其 可組合性。規(guī)則可以像樂高積木一樣嵌套使用。這意味著你可以用 @{case} 的結(jié)果去驅(qū)動(dòng) @{and} 或者在 @{else} 里寫一組 @{if}
比如一個(gè)常見的權(quán)限控制場景:
如果是管理員 (ADMIN),查詢所有數(shù)據(jù);
如果是部門經(jīng)理 (MGR),查詢本部門數(shù)據(jù);
如果是普通員工,只能查自己的數(shù)據(jù)。
}注意看,外層的 @{and} 會(huì)自動(dòng)處理連接詞:
當(dāng) role 是 'ADMIN' 時(shí),@{case} 輸出空,整個(gè) @{and} 消失。
當(dāng) role 是 'MGR' 時(shí),內(nèi)部輸出 dept_id = ?,外層自動(dòng)加上 AND。
這種自然的嵌套組合,讓你能用 SQL 結(jié)構(gòu)直接表達(dá)復(fù)雜的業(yè)務(wù)邏輯,而不是在 Java 代碼和 XML 之間反復(fù)橫跳。
這就結(jié)束了?
規(guī)則的強(qiáng)大之處在于無處不在。你不需要為了使用動(dòng)態(tài) SQL 而強(qiáng)迫自己切換開發(fā)模式。無論你身處哪個(gè)層級(jí),dbVisitor 的動(dòng)態(tài)規(guī)則都能無縫集成。
1. 在 編程式 API (JdbcTemplate) 中使用
不需要 StringBuilder,不需要拼接字符串。
"SELECT * FROM users @{and, name = :name}", args);2. 在 聲明式 API (注解) 中使用
徹底擺脫 @Script 或者
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.