使用 jdbc 或類似的框架导帝,動(dòng)態(tài)拼接 SQL 是很痛苦的堡称。比如根據(jù)當(dāng)前日期選擇數(shù)據(jù)表、根據(jù)傳入的參數(shù)決定更新哪些字段等墙贱,都是比較常用的動(dòng)態(tài)查詢热芹。MyBatis 擁有強(qiáng)大的動(dòng)態(tài) SQL 功能,可以在任何 SQL 語(yǔ)句中使用惨撇。MyBatis 的動(dòng)態(tài) SQL 主要使用以下幾個(gè)元素來(lái)實(shí)現(xiàn):
單一條件:if
多個(gè)條件:choose, when, otherwise
自動(dòng)封裝:trim, where, set
遍歷集合:foreach
if ?
if 用于檢測(cè)條件伊脓,動(dòng)態(tài)包含 SQL 語(yǔ)句。例如下面的語(yǔ)句中魁衙,根據(jù)輸入的 title 是否為空來(lái)決定是否在查詢條件中增加 title 搜索條件报腔。
<select id="select" resultType="Person"> ? ?SELECT * FROM Person WHERE state = ‘ACTIVE’ ?
? ?<if test="title != null"> ? ? ? ?AND title like #{title} ?
? ?</if>
</select>
choose, when, otherwise? ?
choose 元素提供了類似于 Java 語(yǔ)言中的 switch 功能,可以從多個(gè)選項(xiàng)中選擇一個(gè)加入 SQL 語(yǔ)句剖淀。
例如下面的語(yǔ)句纯蛾,使用了兩個(gè) when 和一個(gè) otherwise,類似于 switch 中的 case 和 default祷蝌。
<select id="select" resultType="Person"> ? ?SELECT * FROM Person WHERE state = ‘ACTIVE’ ?
? ?<choose> ? ? ? ?<when test="title != null"> ? ? ? ? ?AND title like #{title} ? ?
? ? ? ?</when> ? ? ? ?<when test="sex != null"> ? ? ? ? ?AND sex = #{sex} ? ?
? ? ? ?</when> ? ? ? ?<otherwise> ? ? ? ? ?AND height = 170
? ? ? ?</otherwise> ? ?</choose>
</select>
trim, where, set? ?
trim 元素可以用于為 SQL 語(yǔ)句增加前綴茅撞、后綴帆卓,并去除指定的開(kāi)頭和結(jié)尾巨朦。一共有四個(gè)屬性:
prefix:語(yǔ)句的前綴;
prefixOverrides:去除開(kāi)頭剑令;
suffix:語(yǔ)句的后綴糊啡;
suffixOverrides:去除結(jié)尾。
在下面的語(yǔ)句中吁津,trim 會(huì)先刪除 somesql 的開(kāi)頭和結(jié)尾棚蓄,然后再增加前綴和后綴。
<trim prefix="前綴" prefixOverrides="去除開(kāi)頭" suffix="后綴" suffixOverrides="去除結(jié)尾"> somesql
</trim>
假設(shè)使用 if 語(yǔ)句增加兩個(gè)動(dòng)態(tài)條件碍脏,如下所示梭依。如果只滿足第二個(gè)條件,或者兩個(gè)條件都不滿足典尾,最終得到的 SQL 是一個(gè)有 WHERE 但沒(méi)有條件的非法 SQL役拴。
<select id="select" resultType="Person"> ? ?SELECT * FROM Person WHERE ?
? ?<if test="sex != null"> ? ? ? ?sex = #{sex} ?
? ?</if> ? ?<if test="title != null"> ? ? ? ?AND title like #{title} ?
? ?</if>
</select>
使用 where 元素可以避免這一點(diǎn),如下所示钾埂。where 元素可以檢測(cè)內(nèi)部的查詢條件是否合法河闰,比如為空科平、多了 AND / OR,并進(jìn)行處理使 SQL 語(yǔ)句合法姜性。經(jīng)過(guò) where 元素處理后瞪慧,無(wú)論內(nèi)部 if 元素是否成立,我們都可以得到合法的 SQL 語(yǔ)句部念。
<select id="select" resultType="Person"> ? ?SELECT * FROM Person ?
? ?<where> ? ? ? ?<if test="sex != null"> ? ? ? ? ? ?sex = #{sex} ? ?
? ? ? ?</if> ? ? ? ?<if test="title != null"> ? ? ? ? ? ?AND title like #{title} ? ?
? ? ? ?</if> ? ?</where>
</select>
同樣地弃酌,update 語(yǔ)句中也可以使用 set 元素來(lái)實(shí)現(xiàn)類似于 where 元素的功能。在如下的示例中儡炼,set 元素確保了 SQL 語(yǔ)句中的 SET 永遠(yuǎn)是合法的矢腻,它能自動(dòng)處理 SET 為空、結(jié)尾多逗號(hào)射赛,并自動(dòng)拼接 SET 字符串多柑。
<update id="update"> ? ?update Person ? ?
? ?<set> ? ? ? ?<if test="title != null">
? ? ? ? ? ?title=#{title},
? ? ? ?</if> ? ? ? ?<if test="sex != null">
? ? ? ? ? ?sex=#{sex},
? ? ? ?</if> ? ?</set> ? ?where id=#{id}
</update>
foreach? ?
foreach 用于處理集合,比如批量插入楣责、批量查詢條件等情況竣灌,支持 List、Array秆麸、Set初嘹、Map 等。在下面的例子中沮趣,查詢條件是一個(gè) list屯烦,使用 in 來(lái)查詢。
<select id="select" resultType="Person"> ? ?SELECT * FROM Person WHERE id in ?
? ?<foreach item="item" index="index" collection="list" ? ? ?open="(" separator="," close=")"> ? ? ? ?#{item}
? ?</foreach>
</select>
foreach 的屬性定義如下:
Item:集合中元素迭代的別名房铭,如果集合為 map 這里是 value驻龟;
index:集合中元素迭代的索引,如果集合為 map 這里是 key缸匪;
collection:集合的類型翁狐;
open:語(yǔ)句的前綴;
separator:語(yǔ)句的分隔符凌蔬;
close:語(yǔ)句的后綴露懒。
分享學(xué)習(xí)筆記和技術(shù)總結(jié),內(nèi)容涉及 Java 進(jìn)階砂心、架構(gòu)設(shè)計(jì)懈词、前沿技術(shù)、算法與數(shù)據(jù)結(jié)構(gòu)辩诞、數(shù)據(jù)庫(kù)坎弯、中間件等多個(gè)領(lǐng)域,歡迎關(guān)注。本文首發(fā)于微信公眾號(hào)“后端開(kāi)發(fā)那點(diǎn)事兒”荞怒。