1. 程式人生 > >MyBatis動態SQL————MyBatis動態SQL標簽的用法

MyBatis動態SQL————MyBatis動態SQL標簽的用法

efi 數組 cnblogs 朋友 正常 scm jdbc pojo 動態語言

1.MyBatis動態SQL

MyBatis 的強大特性之一便是它的動態 SQL,即拼接SQL字符串。如果你有使用 JDBC 或其他類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句有多麽痛苦。拼接的時候要確保不能忘了必要的空格,還要註意省掉列名列表最後的逗號。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。

通常使用動態 SQL 不可能是獨立的一部分,MyBatis 當然使用一種強大的動態 SQL 語言來改進這種情形,這種語言可以被用在任意的 SQL 映射語句中。

動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文本處理器相似。在 MyBatis 之前的版本中,有很多的元素需要來了解。MyBatis 3 大大提升了它們,現在用不到原先一半的元素就可以了。MyBatis 采用功能強大的基於 OGNL 的表達式來消除其他元素。

2.動態SQL標簽:ifchoose (when, otherwise)trim (where, set)foreach

2.1  if標簽:直接上代碼

<select id="queryByIdAndTitle"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 1=1 
  <if test="id!= null and title!=null">
    AND id=#{id} and title=#{title}
  </if>
</select>

註:if標簽一般用於非空驗證,如上例,若id為空,if標簽裏的代碼,將不會執行,反之,則會執行。

2.2  choose(when,otherwise)標簽:直接上代碼

<select id="queryBy"
     resultType="Blog">
  SELECT * FROM BLOG WHERE 1=1
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <otherwise>
      AND id= 1
    </otherwise>
  </choose>
</select>

註:choose(when,otherwise)標簽相當於switch(case,default) ,如上例,若title 為空,when標簽裏的代碼,將不會執行,默認執行otherwise標簽裏面的代碼。

2.3  trim(where,set)標簽:直接上代碼

<select id="queryBy" resultType="com.scme.pojo.User" parameterType="com.scme.pojo.User">
                 select * from user 
                 <where>
                         <if test="username!=null and password!=null">
                             and username=#{username} and password=#{password}
                         </if>
                 </where>
</select>

註:假設上例傳入的username,password不為空,代碼就可以運行成功!但朋友們可能有疑問了,實際上執行的sql語句是什麽呢?其實,sql為:select * from user

where username=? and password=? 朋友們是否發現,where標簽代替了sql中where關鍵字,但if中的and不見了。其實where標簽可以自動去除是“AND”或“OR”開頭的sql中的“AND”或“OR”關鍵字

如果 where 元素沒有按正常套路出牌,我們還是可以通過自定義 trim 元素來定制sql,實現where標簽的效果。代碼如下:

<select id="queryBy" resultType="com.scme.pojo.User" parameterType="com.scme.pojo.User">
                 select * from user 
                 <trim prefix="WHERE" prefixOverrides="AND |OR ">
                          <if test="username!=null and password!=null">
                             and username=#{username} and password=#{password}
                         </if>
                </trim>
                 <!-- 效果同上
          <where> <if test="username!=null and password!=null"> and username=#{username} and password=#{password} </if> </where>
--> </select>

set標簽,代碼如下:

<update id="updateUser" parameterType="com.scme.pojo.User">
                 update user 
                 <set>
                     <if test="username!=null">
                             username=#{username}
                     </if>
                 </set>
                 <where> 
                     <if test="id!=null">
                             id=#{id}
                     </if>
                 </where>
         </update>

註:set標簽功能和where標簽差不多,set標簽代替了sql中set關鍵字,set標簽可以自動去除sql中的多余的“,”

同理,trim標簽也可以實現set標簽的功能

<update id="updateUser" parameterType="com.scme.pojo.User">
                 update user 
         <trim prefix="set" prefixOverrides=",">
              <if test="username!=null"> username=#{username} </if> 
        </trim>
  
        <where>
    
            <if test="id!=null"> id=#{id} </if>
          
        </where>

</update>

2.4  foreach標簽:foreach標簽實現批量刪除,直接上代碼

<delete id="batchDelete" parameterType="java.lang.String">
  delete from user
  where id in
  <foreach item="id" index="index" collection="list"
      open="(" separator="," close=")">
        #{id}
  </foreach>
</delete >

註:foreach標簽可叠代任何對象(如列表、集合等)和任何的字典或者數組對象傳遞給foreach作為集合參數,當使用可叠代對象或者數組時,index是當前叠代的次數,item的值是本次叠代獲取的元素當使用字典(或者Map.Entry對象的集合)時,index是鍵,item是值。collection標簽可以填(‘list‘,‘array‘,‘map‘)

foreach元素的屬性主要有 item,index,collection,open,separator,close。

item表示集合中每一個元素進行叠代時的別名;

index指 定一個名字,用於表示在叠代過程中,每次叠代到的位置;

open表示該語句以什麽開始,

separator表示在每次進行叠代之間以什麽符號作為分隔符;

close表示以什麽結束。

3.bind

bind 元素可以從 OGNL 表達式中創建一個變量並將其綁定到上下文。比如:

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

4.Multi-db vendor support

一個配置了“_databaseId”變量的 databaseIdProvider 對於動態代碼來說是可用的,這樣就可以根據不同的數據庫廠商構建特定的語句。比如下面的例子:

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

動態 SQL 中可插拔的腳本語言

MyBatis 從 3.2 開始支持可插拔的腳本語言,因此你可以在插入一種語言的驅動(language driver)之後來寫基於這種語言的動態 SQL 查詢。

可以通過實現下面接口的方式來插入一種語言:

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 文件中將它設置為默認語言:

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

除了設置默認語言,你也可以針對特殊的語句指定特定語言,這可以通過如下的 lang 屬性來完成:

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

或者在你正在使用的映射中加上註解 @Lang 來完成:

public interface Mapper {
  @Lang(MyLanguageDriver.class)
  @Select("SELECT * FROM BLOG")
  List<Blog> selectBlog();

註意 可以將 Apache Velocity 作為動態語言來使用,更多細節請參考 MyBatis-Velocity 項目。

如有幫助,請關註!

MyBatis動態SQL————MyBatis動態SQL標簽的用法