MyBatis-3.動(dòng)態(tài)SQL

MyBatis有以下元素用于處理動(dòng)態(tài)SQL:

  • if
  • choose(when,otherwise)
  • trim(where,set)
  • foreach

if

通常用在where子句的一部分:

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

多個(gè)條件:

<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>

choose, when, otherwise

從所有條件語(yǔ)句中挑選一個(gè),例如:

<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>

trim,where,set

可以用來(lái)處理所有條件都需要被選擇的情況:

<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>

where 元素只會(huì)在至少有一個(gè)子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語(yǔ)句的開頭為“AND”或“OR”,where 元素也會(huì)將它們?nèi)コ?/p>

<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>

可以通過(guò)trim元素定制where元素的功能,和where元素等價(jià)的trim元素為:

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

prefixOverrides 屬性會(huì)忽略通過(guò)管道分隔的文本序列(注意此例中的空格也是必要的)。
它的作用是移除所有指定在 prefixOverrides屬性中的內(nèi)容,并且插入 prefix屬性中指定的內(nèi)容。

動(dòng)態(tài)更新語(yǔ)句中需要用到set,set元素可以用于動(dòng)態(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 元素會(huì)動(dòng)態(tài)前置 SET 關(guān)鍵字,同時(shí)也會(huì)刪掉無(wú)關(guān)的逗號(hào),因?yàn)橛昧藯l件語(yǔ)句之后很可能就會(huì)在生成的 SQL 語(yǔ)句的后面留下這些逗號(hào)。(譯者注:因?yàn)橛玫氖恰癷f”元素,若最后一個(gè)“if”沒有匹配上而前面的匹配上,SQL 語(yǔ)句的最后就會(huì)有一個(gè)逗號(hào)遺留)

set 元素等價(jià)的自定義 trim 元素(注意這里我們刪去的是后綴值,同時(shí)添加了前綴值。):

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

foreach

對(duì)一個(gè)集合進(jìn)行遍歷,通常用在構(gòu)建IN條件語(yǔ)句的時(shí)候:

<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>

可以將任何可迭代對(duì)象(如 List、Set 等)、Map 對(duì)象或者數(shù)組對(duì)象傳遞給 foreach 作為集合參數(shù)。當(dāng)使用可迭代對(duì)象或者數(shù)組時(shí),index 是當(dāng)前迭代的次數(shù),item 的值是本次迭代獲取的元素。當(dāng)使用 Map 對(duì)象(或者 Map.Entry 對(duì)象的集合)時(shí),index 是鍵,item 是值。

bind

bind元素可以從ONGL表達(dá)式中創(chuàng)建一個(gè)變量并將其綁定到上下文,例如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

多數(shù)據(jù)庫(kù)支持

一個(gè)配置了“_databaseId”變量的 databaseIdProvider 可用于動(dòng)態(tài)代碼中,這樣就可以根據(jù)不同的數(shù)據(jù)庫(kù)廠商構(gòu)建特定的語(yǔ)句。比如下面的例子:

<insert id="insert">
  <selectKey keyProperty="id" resultType="int" order="BEFORE">
    <if test="_databaseId == 'oracle'">
      select seq_users.nextval from dual
    </if>
    <if test="_databaseId == 'db2'">
      select nextval for seq_users from sysibm.sysdummy1"
    </if>
  </selectKey>
  insert into users values (#{id}, #{name})
</insert>

動(dòng)態(tài) SQL 中的可插拔腳本語(yǔ)言

插入一種腳本語(yǔ)言驅(qū)動(dòng),并基于這種語(yǔ)言來(lái)編寫動(dòng)態(tài) SQL 查詢語(yǔ)句。
可以通過(guò)實(shí)現(xiàn)以下接口來(lái)插入一種語(yǔ)言:

public interface LanguageDriver {
  ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql);
  SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType);
  SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType);
}

然后在 mybatis-config.xml 文件中將它設(shè)置為默認(rèn)語(yǔ)言:

<typeAliases>
  <typeAlias type="org.sample.MyLanguageDriver" alias="myLanguage"/>
</typeAliases>
<settings>
  <setting name="defaultScriptingLanguage" value="myLanguage"/>
</settings>

除了設(shè)置默認(rèn)語(yǔ)言,也可以針對(duì)特殊的語(yǔ)句指定特定語(yǔ)言,可以通過(guò)如下的 lang 屬性來(lái)完成:

<select id="selectBlog" lang="myLanguage">
  SELECT * FROM BLOG
</select>

或者,如果你使用的是映射器接口類,在抽象方法上加上 @Lang 注解即可:

public interface Mapper {
  @Lang(MyLanguageDriver.class)
  @Select("SELECT * FROM BLOG")
  List<Blog> selectBlog();
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,248評(píng)論 0 4
  • 4.動(dòng)態(tài)SQL MyBatis 的強(qiáng)大特性之一便是它的動(dòng)態(tài) SQL。如果你有使用 JDBC 或其他類似框架的經(jīng)驗(yàn),...
    王偵閱讀 204評(píng)論 0 0
  • 天空剝開一只繭 撕裂厚重的外衣,放逐搖曳的靈魂 退去一朝花色 蒙上灰塵四處游弋 一無(wú)所有等一場(chǎng)風(fēng)雨 無(wú)所期待沉淀的...
    清若閱讀 983評(píng)論 26 42
  • 窗臺(tái)上,月光如晝。我踩著斑駁的黑影,努力地把頭向外探伸,尋望見一輪圓圓的月亮,皎潔似玉盤,安靜的放置在不遠(yuǎn)處的幾戶...
    昇夫閱讀 496評(píng)論 2 12

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