App下載

MyBatis中怎么使用動態(tài)SQL標(biāo)簽?使用方法解析

猿友 2021-08-05 12:25:42 瀏覽數(shù) (1756)
反饋

MyBatis 作為一款非常優(yōu)秀的持久層框架,在目前項(xiàng)目開發(fā)中應(yīng)用的十分廣泛。本篇文章,將和大家介紹 MyBatis 中一個強(qiáng)大的特性之一,動態(tài) SQL 以及具體的使用方法。

1.MyBatis動態(tài)SQL

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

通常使用動態(tài) SQL 不可能是獨(dú)立的一部分,MyBatis 當(dāng)然使用一種強(qiáng)大的動態(tài) SQL 語言來改進(jìn)這種情形,這種語言可以被用在任意的 SQL 映射語句中。

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

2.動態(tài)SQL標(biāo)簽:if,choose (when, otherwise),trim (where, set),foreach

2.1 if標(biāo)簽:直接上代碼

<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標(biāo)簽一般用于非空驗(yàn)證,如上例,若id為空,if標(biāo)簽里的代碼,將不會執(zhí)行,反之,則會執(zhí)行。

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

<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)標(biāo)簽相當(dāng)于switch(case,default) ,如上例,若title 為空,when標(biāo)簽里的代碼,將不會執(zhí)行,默認(rèn)執(zhí)行otherwise標(biāo)簽里面的代碼。

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

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

注:假設(shè)上例傳入的username,password不為空,代碼就可以運(yùn)行成功!但朋友們可能有疑問了,實(shí)際上執(zhí)行的sql語句是什么呢?其實(shí),sql為:select * from user

 where username=? and password=?  朋友們是否發(fā)現(xiàn),where標(biāo)簽代替了sql中where關(guān)鍵字,但if中的and不見了。其實(shí)where標(biāo)簽可以自動去除是“AND”或“OR”開頭的sql中的“AND”或“OR”關(guān)鍵字。

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

<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標(biāo)簽,代碼如下:

<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標(biāo)簽功能和where標(biāo)簽差不多,set標(biāo)簽代替了sql中set關(guān)鍵字,set標(biāo)簽可以自動去除sql中的多余的“,”

同理,trim標(biāo)簽也可以實(shí)現(xiàn)set標(biāo)簽的功能

<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標(biāo)簽:foreach標(biāo)簽實(shí)現(xiàn)批量刪除,直接上代碼

<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標(biāo)簽可迭代任何對象(如列表、集合等)和任何的字典或者數(shù)組對象傳遞給foreach作為集合參數(shù),當(dāng)使用可迭代對象或者數(shù)組時,index是當(dāng)前迭代的次數(shù),item的值是本次迭代獲取的元素。當(dāng)使用字典(或者M(jìn)ap.Entry對象的集合)時,index是鍵,item是值。collection標(biāo)簽可以填('list','array','map')。

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

item表示集合中每一個元素進(jìn)行迭代時的別名;

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

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

separator表示在每次進(jìn)行迭代之間以什么符號作為分隔符;

close表示以什么結(jié)束。

3.bind

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

<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 對于動態(tài)代碼來說是可用的,這樣就可以根據(jù)不同的數(shù)據(jù)庫廠商構(gòu)建特定的語句。比如下面的例子:

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

動態(tài) SQL 中可插拔的腳本語言

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

可以通過實(shí)現(xiàn)下面接口的方式來插入一種語言:

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);
}

一旦有了自定義的語言驅(qū)動,你就可以在 mybatis-config.xml 文件中將它設(shè)置為默認(rèn)語言:

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

除了設(shè)置默認(rèn)語言,你也可以針對特殊的語句指定特定語言,這可以通過如下的 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 作為動態(tài)語言來使用,更多細(xì)節(jié)請參考 MyBatis-Velocity 項(xiàng)目。

到此這篇關(guān)于 MyBatis中如何使用動態(tài)SQL標(biāo)簽的文章就介紹到這了,想要了解更多相關(guān)MyBatis動態(tài)SQL標(biāo)簽內(nèi)容請搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,也希望大家以后多多支持!


0 人點(diǎn)贊