使用 jdbc 或類似的框架,動態(tài)拼接 SQL 是很痛苦的。比如根據(jù)當前日期選擇數(shù)據(jù)表、根據(jù)傳入的參數(shù)決定更新哪些字段等,都是比較常用的動態(tài)查詢。MyBatis 擁有強大的動態(tài) SQL 功能,可以在任何 SQL 語句中使用。MyBatis 的動態(tài) SQL 主要使用以下幾個元素來實現(xiàn):
單一條件:if
多個條件:choose, when, otherwise
自動封裝:trim, where, set
遍歷集合:foreach
if ?
if 用于檢測條件,動態(tài)包含 SQL 語句。例如下面的語句中,根據(jù)輸入的 title 是否為空來決定是否在查詢條件中增加 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 語言中的 switch 功能,可以從多個選項中選擇一個加入 SQL 語句。
例如下面的語句,使用了兩個 when 和一個 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 語句增加前綴、后綴,并去除指定的開頭和結尾。一共有四個屬性:
prefix:語句的前綴;
prefixOverrides:去除開頭;
suffix:語句的后綴;
suffixOverrides:去除結尾。
在下面的語句中,trim 會先刪除 somesql 的開頭和結尾,然后再增加前綴和后綴。
<trim prefix="前綴" prefixOverrides="去除開頭"
suffix="后綴" suffixOverrides="去除結尾">
somesql
</trim>假設使用 if 語句增加兩個動態(tài)條件,如下所示。如果只滿足第二個條件,或者兩個條件都不滿足,最終得到的 SQL 是一個有 WHERE 但沒有條件的非法 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 元素可以避免這一點,如下所示。where 元素可以檢測內部的查詢條件是否合法,比如為空、多了 AND / OR,并進行處理使 SQL 語句合法。經(jīng)過 where 元素處理后,無論內部 if 元素是否成立,我們都可以得到合法的 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> ? ?</where>
</select>
同樣地,update 語句中也可以使用 set 元素來實現(xiàn)類似于 where 元素的功能。在如下的示例中,set 元素確保了 SQL 語句中的 SET 永遠是合法的,它能自動處理 SET 為空、結尾多逗號,并自動拼接 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 等。在下面的例子中,查詢條件是一個 list,使用 in 來查詢。
<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:語句的前綴;
separator:語句的分隔符;
close:語句的后綴。
分享學習筆記和技術總結,內容涉及 Java 進階、架構設計、前沿技術、算法與數(shù)據(jù)結構、數(shù)據(jù)庫、中間件等多個領域,歡迎關注。本文首發(fā)于微信公眾號“后端開發(fā)那點事兒”。