初識 Mybatis(二)—— 動態(tài) SQL

這篇文章來自我的博客

正文之前

上一篇介紹了 Mybatis 的基本用法,這一篇我們著重介紹一下 Mybatis 對 SQL 拼接的支持,在之前寫 JDBC 代碼的時(shí)候,SQL 拼接的代碼一直是處于一種很繁瑣的狀態(tài),拼接一張表的代碼動則幾十行,用 Mybatis 就只需要幾行就搞定了

主要內(nèi)容:

  1. if 標(biāo)簽
  2. where 標(biāo)簽
  3. 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ò)誤

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容