<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MyBatis 中為什么不建議使用 where 1=1?

          共 1900字,需瀏覽 4分鐘

           ·

          2021-11-19 15:21

          作者 | 王磊

          來源 | Java中文社群(ID:javacn666)

          轉(zhuǎn)載請(qǐng)聯(lián)系授權(quán)(微信ID:GG_Stone)

          最近接手了一個(gè)老項(xiàng)目,“愉悅的心情”自然無以言表,做開發(fā)的朋友都懂,這里就不多說了,都是淚...

          接手老項(xiàng)目,自然是要先熟悉一下業(yè)務(wù)代碼,然而在翻閱 mapper 文件時(shí),發(fā)現(xiàn)了一個(gè)比較詭異的事情。這里給出簡(jiǎn)化后的業(yè)務(wù)代碼:


          mapper?PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          <mapper?namespace="com.example.demo.mapper.UserMapper">
          ????<select?id="list"?resultType="com.example.demo.model.User">
          ????????select?*?from?user
          ????????where?1=1
          ????????<if?test="name!=null">
          ????????????and?name=#{name}
          ????????if>
          ????????<if?test="password!=null">
          ????????????and?password=#{password}
          ????????if>
          ????select>
          mapper>

          機(jī)智的小伙伴可能已經(jīng)看出了問題,在眾多 mapper 中發(fā)現(xiàn)了一個(gè)相同的想象,幾乎所有的 mapper 中都包含了一個(gè)無用的拼接 SQL:where 1=1。作為一個(gè)幾乎有代碼潔癖癥的人,自然是忍不住動(dòng)手改造一番了。

          錯(cuò)誤的改造方式

          既然是去掉 where 1=1,那最簡(jiǎn)單的方式就是將它直接從代碼中刪除了,如下代碼所示:

          "1.0"?encoding="UTF-8"?>
          "-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          "com.example.demo.mapper.UserMapper">
          ????"list"?resultType="com.example.demo.model.User">
          ????????select?*?from?user
          ????????????where
          ????????????<if?test="name!=null">
          ????????????????name=#{name}
          ????????????if>
          ????????????<if?test="password!=null">
          ????????????????and?password=#{password}
          ????????????if>
          ????

          以上代碼刪除了 1=1,并且把第一個(gè) name 查詢中的 and 去掉了,以防 SQL 查詢報(bào)錯(cuò)。

          但這樣就沒問題了嗎?我們直接來看結(jié)果,當(dāng)包含參數(shù) name 查詢時(shí),結(jié)果如下:一切順理成章,完美的一塌糊涂。?

          然而,當(dāng)省略 name 參數(shù)時(shí)(因?yàn)?name 為非必要參數(shù),所以可以省略),竟然引發(fā)了以下異常:又或者只有 password 查詢時(shí),結(jié)果也是一樣:都是報(bào)錯(cuò)信息,那腫么辦呢?難不成把 1=1 恢復(fù)回去?

          正確的改進(jìn)方式

          其實(shí)不用,在 MyBatis 中早已經(jīng)想到了這個(gè)問題,我們可以將 SQL 中的 where 關(guān)鍵字換成 MyBatis 中的標(biāo)簽,并且給每個(gè)標(biāo)簽內(nèi)都加上 and 拼接符,這樣問題就解決了,如下代碼所示:


          mapper?PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
          <mapper?namespace="com.example.demo.mapper.UserMapper">
          ????<select?id="list"?resultType="com.example.demo.model.User">
          ????????select?*?from?user
          ????????<where>
          ????????????<if?test="name!=null">
          ???????????????and?name=#{name}
          ????????????if>
          ????????????<if?test="password!=null">
          ????????????????and?password=#{password}
          ????????????if>
          ????????where>
          ????select>
          mapper>

          代碼改造完成之后,接下來我們來測(cè)試一下所有的請(qǐng)求場(chǎng)景。

          不傳任何參數(shù)的請(qǐng)求

          此時(shí)我們可以不傳遞任何參數(shù)(查詢所有數(shù)據(jù)),如下圖所示:生成的 SQL 語句如下:

          傳遞 1 個(gè)參數(shù)的請(qǐng)求

          也可以傳遞 1 個(gè)參數(shù),根據(jù) name 進(jìn)行查詢,如下圖所示:生成的 SQL 如下圖所示:也可以只根據(jù) password 進(jìn)行查詢,如下圖所示:生成的 SQL 如下圖所示:

          傳遞 2 個(gè)參數(shù)的請(qǐng)求

          也可以根據(jù) name 加 password 的方式進(jìn)行聯(lián)合查詢,如下圖所示:生成的 SQL 如下圖所示:

          用法解析

          我們驚喜的發(fā)現(xiàn),在使用了標(biāo)簽之后,無論是任何查詢場(chǎng)景,傳一個(gè)或者傳多個(gè)參數(shù),或者直接不傳遞任何參數(shù),都可以輕松搞定。

          首先,標(biāo)簽會(huì)判斷,如果沒有任何參數(shù),則不會(huì)在 SQL 語句中拼接 where 查詢,反之才會(huì)拼接 where 查詢;其次在查詢的標(biāo)簽中,每個(gè)標(biāo)簽都可以加 and 關(guān)鍵字,MyBatis 會(huì)自動(dòng)將第一個(gè)條件前面的 and 關(guān)鍵字刪除掉,從而不會(huì)導(dǎo)致 SQL 語法錯(cuò)誤,這一點(diǎn)官方文檔中也有說明,如下圖所示:

          總結(jié)

          在 MyBatis 中,建議盡量避免使用無意義的 SQL 拼接 ?where 1=1,我們可以使用標(biāo)簽來替代 where 1=1,這樣的寫既簡(jiǎn)潔又優(yōu)雅,何樂而不為呢?以上內(nèi)容僅為個(gè)人觀點(diǎn),歡迎評(píng)論區(qū)留言討論。


          推薦閱讀:

          為什么阿里把MySQL的事務(wù)隔離級(jí)別改成RC?

          一個(gè)架構(gòu)師的緩存修煉之路

          Redis主節(jié)點(diǎn)的Key已過期的處理

          Redis 哨兵模式


          關(guān)號(hào)互聯(lián)網(wǎng)全棧架構(gòu)價(jià)

          瀏覽 63
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大伊香蕉在线播放 | 在线观看女人爽网 | www.人人操.com | 久久免费91 | 色999一区二 |