動態(tài) SQL 入坑

動態(tài)SQL

1. if

這條語句提供了可選的查找文本功能赶促。如果不傳入 “title”,那么所有處于 “ACTIVE” 狀態(tài)的 BLOG 都會返回挟炬;如果傳入了 “title” 參數(shù)鸥滨,那么就會對 “title” 一列進行模糊查找并返回對應的 BLOG 結果(細心的讀者可能會發(fā)現(xiàn),“title” 的參數(shù)值需要包含查找掩碼或通配符字符)辟宗。

<select id="findActiveBlogWithTitleLike" resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

如果希望通過 “title” 和 “author” 兩個參數(shù)進行可選搜索該怎么辦呢爵赵?首先,我想先將語句名稱修改成更名副其實的名稱泊脐;接下來空幻,只需要加入另一個條件即可。

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

2. choose容客、when秕铛、otherwise

有時候约郁,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用但两。針對這種情況鬓梅,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句谨湘。

還是上面的例子绽快,但是策略變?yōu)椋簜魅肓?“title” 就按 “title” 查找,傳入了 “author” 就按 “author” 查找的情形紧阔。若兩者都沒有傳入坊罢,就返回標記為 featured 的 BLOG(這可能是管理員認為,與其返回大量的無意義隨機 Blog擅耽,還不如返回一些由管理員挑選的 Blog)活孩。

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

3. trim、where乖仇、set

前面幾個例子已經(jīng)合宜地解決了一個臭名昭著的動態(tài) SQL 問題『度澹現(xiàn)在回到之前的 “if” 示例,這次我們將 “state = ‘ACTIVE’” 設置成動態(tài)條件乃沙,看看會發(fā)生什么起趾。

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG
  WHERE
  <if test="state != null">
    state = #{state}
  </if>
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

如果沒有匹配的條件會怎么樣?最終這條 SQL 會變成這樣:

SELECT * FROM BLOG
WHERE

這會導致查詢失敗崔涂。如果匹配的只是第二個條件又會怎樣阳掐?這條 SQL 會是這樣:

SELECT * FROM BLOG
WHERE
AND title like ‘someTitle’

這個查詢也會失敗始衅。這個問題不能簡單地用條件元素來解決冷蚂。這個問題是如此的難以解決,以至于解決過的人不會再想碰到這種問題汛闸。

MyBatis 有一個簡單且適合大多數(shù)場景的解決辦法蝙茶。而在其他場景中,可以對其進行自定義以符合需求诸老。而這隆夯,只需要一處簡單的改動:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素只會在子元素返回任何內(nèi)容的情況下才插入 “WHERE” 子句。而且别伏,若子句的開頭為 “AND” 或 “OR”蹄衷,where 元素也會將它們?nèi)コ?/p>

如果 where 元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定制 where 元素的功能厘肮。比如愧口,和 where 元素等價的自定義 trim 元素為:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

prefixOverrides 屬性會忽略通過管道符分隔的文本序列(注意此例中的空格是必要的)。

上述例子會移除所有 prefixOverrides 屬性中指定的內(nèi)容类茂,并且插入 prefix 屬性中指定的內(nèi)容耍属。

用于動態(tài)更新語句的類似解決方案叫做 set托嚣。set 元素可以用于動態(tài)包含需要更新的列,忽略其它不更新的列厚骗。比如:

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

這個例子中示启,set 元素會動態(tài)地在行首插入 SET 關鍵字,并會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)领舰。

來看看與 set 元素等價的自定義 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

foreach

動態(tài) SQL 的另一個常見使用場景是對集合進行遍歷(尤其是在構建 IN 條件語句的時候)夫嗓。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

script

要在帶注解的映射器接口類中使用動態(tài) SQL,可以使用 script 元素冲秽。比如:

    @Update({"<script>",
      "update Author",
      "  <set>",
      "    <if test='username != null'>username=#{username},</if>",
      "    <if test='password != null'>password=#{password},</if>",
      "    <if test='email != null'>email=#{email},</if>",
      "    <if test='bio != null'>bio=#{bio}</if>",
      "  </set>",
      "where id=#{id}",
      "</script>"})
    void updateAuthorValues(Author author);

bind 元素允許你在 OGNL 表達式以外創(chuàng)建一個變量啤月,并將其綁定到當前的上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末劳跃,一起剝皮案震驚了整個濱河市谎仲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌刨仑,老刑警劉巖郑诺,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杉武,居然都是意外死亡辙诞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門轻抱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來飞涂,“玉大人,你說我怎么就攤上這事祈搜〗系辏” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵容燕,是天一觀的道長梁呈。 經(jīng)常有香客問我,道長蘸秘,這世上最難降的妖魔是什么官卡? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮醋虏,結果婚禮上寻咒,老公的妹妹穿的比我還像新娘。我一直安慰自己颈嚼,他們只是感情好毛秘,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著粘舟,像睡著了一般熔脂。 火紅的嫁衣襯著肌膚如雪佩研。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天霞揉,我揣著相機與錄音旬薯,去河邊找鬼。 笑死适秩,一個胖子當著我的面吹牛绊序,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播秽荞,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骤公,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扬跋?” 一聲冷哼從身側響起阶捆,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钦听,沒想到半個月后洒试,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡朴上,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年垒棋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痪宰。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叼架,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衣撬,到底是詐尸還是另有隱情乖订,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布淮韭,位于F島的核電站垢粮,受9級特大地震影響,放射性物質發(fā)生泄漏靠粪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一毫蚓、第九天 我趴在偏房一處隱蔽的房頂上張望占键。 院中可真熱鬧,春花似錦元潘、人聲如沸畔乙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牲距。三九已至返咱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間牍鞠,已是汗流浹背咖摹。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留难述,地道東北人萤晴。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像胁后,于是被迫代替她去往敵國和親店读。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容