
這篇文章來自我的博客
正文之前
上一篇介紹了 Mybatis 的基本用法,這一篇我們著重介紹一下 Mybatis 對 SQL 拼接的支持,在之前寫 JDBC 代碼的時(shí)候,SQL 拼接的代碼一直是處于一種很繁瑣的狀態(tài),拼接一張表的代碼動則幾十行,用 Mybatis 就只需要幾行就搞定了
主要內(nèi)容:
- if 標(biāo)簽
- where 標(biāo)簽
- trim 標(biāo)簽
正文
1. if 標(biāo)簽
使用 if 標(biāo)簽來判斷參數(shù)是否為空,來達(dá)到 SQL 拼接的效果:
<select id="selectProduct" resultType="bean.Product">
SELECT * FROM product
WHERE id = 1
<if test="name != null">
AND name LIKE #{name}
</if>
</select>
在 if 標(biāo)簽中有一個(gè) test 屬性,它用來進(jìn)行條件判斷,如果 test 屬性中的語句為 true,就將 if 標(biāo)簽中的語句添加至上面的 SQL 語句中,目前,我都是用在 Web 項(xiàng)目中使用 if 標(biāo)簽配合表單的輸入來進(jìn)行模糊查找
那么如果所有的 if 標(biāo)簽都不成立呢?馬上就會說到
2. where 標(biāo)簽
這里給出一條新的 SQL 語句:
<select id="selectProduct" resultType="bean.Product">
SELECT * FROM product
WHERE
<if test="id != null">
id = #{id}
</if>
<if test="name != null">
AND name LIKE #{name}
</if>
</select>
如果上述的所有 if 標(biāo)簽都不成立呢,這 SQL 語句就變?yōu)椋?/p>
SELECT * FROM product
WHERE
這時(shí)候就不能執(zhí)行了,因?yàn)榘l(fā)生了語法錯(cuò)誤,所以我們改用 where 標(biāo)簽:
SELECT * FROM product
<where>
<if test="id != null">
id = #{id}
</if>
<if test="name != null">
AND name LIKE #{name}
</if>
</where>
where 標(biāo)簽存在的條件是至少有一個(gè)子標(biāo)簽存在,也就是至少有一個(gè) if 標(biāo)簽成立,所以如果所有 if 標(biāo)簽都不成立,SQL 語句就變?yōu)椋?/p>
SELECT * FROM product
3. trim 標(biāo)簽
我們假設(shè),在上面的 SQL 語句中還有一個(gè)問題:如果 id 為空,而 name 不為空,那么 SQL 語句就變?yōu)椋?/p>
SELECT * FROM product
WHERE AND name LIKE #{name}
雖然這個(gè)假設(shè)不成立,在 where 標(biāo)簽和接下來要說的 set 標(biāo)簽中不會出現(xiàn)多余的情況(是否可以認(rèn)為是內(nèi)置了 trim 標(biāo)簽),但是我們還是要試一試,多出來一個(gè) AND,看看 trim 標(biāo)簽如何去除:
SELECT * FROM product
<trim prefix="WHERE" prefixOverrides="AND ">
<if test="id != null">
id = #{id}
</if>
<if test="name != null">
AND name LIKE #{name}
</if>
</trim>
將 where 標(biāo)簽換成 trim 標(biāo)簽,prefix 屬性表示我在這個(gè)標(biāo)簽前面需要添加什么,我這里添加 WHERE,因?yàn)槲覀円呀?jīng)把 where 標(biāo)簽去掉了,為了語法正確性,添加 WHERE
prefixOverrides 表示,如果指定的內(nèi)容是多余的(這里指的是 AND以及一個(gè)空格),就會去掉
所以,如果 id 為空,name 不為空,SQL 語句就變?yōu)椋?/p>
SELECT * FROM product
WHERE name LIKE #{name}
這時(shí)候就能正常運(yùn)行了
有的人會想,那如果有多個(gè) AND,豈不是就有多個(gè) WHERE?
稍微修改一下:
<trim prefix="WHERE" prefixOverrides="AND ">
<if test="barcode != null">
AND barcode LIKE #{barcode}
</if>
<if test="name != null">
AND name LIKE #{name}
</if>
<if test="units != null">
AND units LIKE #{units}
</if>
</trim>
其實(shí)有多個(gè) if 標(biāo)簽,要去掉 AND 的就只有第一個(gè)成立的,比如說 barcode 不為空,就用 WHERE 來替換 AND,后面的不管成立不成立,都不會影響語法的正確性
注意,是語法的正確性,不管 name 或 units 是否為空,都不會導(dǎo)致 SQL 語句無法執(zhí)行,因?yàn)?WHERE 后面已經(jīng)有一條 barcode LIKE #{barcode}
4. set 標(biāo)簽
set 標(biāo)簽用于動態(tài)更新,也就是更新那些需要更新的行,我們來看看用法:
UPDATE product
<set>
<if test="barcode != null">
barcode = #{barcode},
</if>
<if test="name != null">
name = #{name},
</if>
...
</set>
這里由于篇幅關(guān)系,只給出更新兩項(xiàng)內(nèi)容的語句,其余的類似
在 if 標(biāo)簽中的語句中最后又一個(gè)逗號,這就和上面說的 AND 是類似的,set 標(biāo)簽會自動去除多余的逗號,否則就會有語法錯(cuò)誤,如果你想用 trim 來達(dá)到這種效果:
UPDATE product
<trim prefix="SET" suffixOverrides=",">
<if test="barcode != null">
barcode = #{barcode},
</if>
<if test="name != null">
name = #{name},
</if>
</trim>
這個(gè)標(biāo)簽表示,去掉多余的逗號,并在前面加上 SET,使其成為語法正確的語句
總而言之,使用動態(tài) SQL 能夠避免 SQL 拼接時(shí)可能會發(fā)生的種種錯(cuò)誤