動態SQL的標簽使用和入門寫法


動態 SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。

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

if

select * from user where 1=1 
<if test="id != null and id != ''">
    and id = #{id}
</if>
<if test="name != null and name != ''">
    and name = #{name}
</if>

為什么使用1=1作為參數都很清楚了,如果沒有1=1且條件if為true,那么拼接的sql語句會變成,是錯誤的拼接

如果沒有匹配又沒有1=1的條件會怎么樣?

select * from user where

如果匹配的只是第二個條件又會怎樣?

select * from user where and name = nameValue

if的多條件使用,即使沒有1=1也不會出現問題,因為此時有一個固定條件,只要確保不出現 where 和 and的連接的情況即可。

<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

<select id="testStudayChoose" resultType="User">
   select * from `user`
    <where>
        <choose>
            <when test="name != null and name != ''">
                and name = #{name}
            </when>
            <when test="password != null and password != ''">
                and password = #{password}
            </when>
            <otherwise>
                and uid = 1
            </otherwise>
        </choose>
    </where>
</select>

下面會講到<where>,其實就是代替了where 1=1。

值得注意的是choose標簽相當於switch,滿足第一個條件以后就不會執行其他語句拼接,例如name和password兩個參數都傳也只會執行name。

而otherwise標簽則是相當於default當條件都不滿足時執行的拼接sql。

trim、where、set

<where> </where>

前面幾個例子已經合宜地解決了一個臭名昭著的動態 SQL 問題。現在回到之前的 “if” 示例,這次我們將 where 1=1 設置成動態條件

<select id="findOneSql" resultType="User">
    select * from `user`
    <where>
        <if test="id != null and id != ''">
            and uid = #{uid}
        </if>
        <if test="birthday != null">
            and birthday = #{birthday}
        </if>
    </where>
</select>

where標簽在if條件都不滿足時取消的where的條件拼接,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除。

trim標簽也可以完成相同的功能

<select id="findOneSql" resultType="User">
    select * from `user`
    <trim prefix="WHERE" prefixOverrides="AND |OR"> 
        <if test="id != null and id != ''">
            and uid = #{uid}
        </if>
        <if test="birthday != null">
            and birthday = #{birthday}
        </if>
    </trim>
</select>

值得注意的是trim標簽中的每個屬性

屬性 描述
prefix 給sql語句拼接的前綴
suffix 給sql語句拼接的后綴
prefixOverrides 去除sql語句前面的關鍵字或者字符,該關鍵字或者字符由prefixOverrides屬性指定,假設該屬性指定為"AND",當sql語句的開頭為"AND",trim標簽將會去除該"AND"
suffixOverrides 去除sql語句后面的關鍵字或者字符,該關鍵字或者字符由suffixOverrides屬性指定

<set></set>

<update id="updateOneSql">
    update `user`
    <set>
        <if test="name != null and name != ''">
            `name` = #{name},
        </if>
        <if test="birthday != null">
            birthday = #{birthday}
        </if>
    </set>
    where uid = #{uid}
</update>
<-- 或使用的寫法 -->
<
trim prefix="SET" suffixOverrides=","> ... </trim>

foreach 

例如使用場景為 uid in () 括號中位多個條件

<select id="setValueListSql" parameterType="java.util.List" resultType="User">
    SELECT * from `user` where uid in
    <foreach collection="list" open="(" separator="," close=")" item="item" index="index">
        #{item}
    </foreach>
</select>
    • collection:表示傳入過來的參數的數據類型。該參數為必選。要做 foreach 的對象,作為入參時,List 對象默認用 list 代替作為鍵,數組對象有 array 代替作為鍵,Map 對象沒有默認的鍵。當然在作為入參時可以使用 @Param(“keyName”) 來設置鍵,設置 keyName 后,list,array 將會失效。 除了入參這種情況外,還有一種作為參數對象的某個字段的時候。舉個例子:
      如果 User 有屬性 List ids。入參是 User 對象,那么這個 collection = “ids” 如果 User 有屬性 Ids ids;其中 Ids 是個對象,Ids 有個屬性 List id;入參是 User 對象,那么 collection = “ids.id”
      • 如果傳入的是單參數且參數類型是一個 List 的時候,collection 屬性值為 list
      • 如果傳入的是單參數且參數類型是一個 array 數組的時候,collection 的屬性值為 array
      • 如果傳入的參數是多個的時候,我們就需要把它們封裝成一個 Map 了,當然單參數也可以封裝成 map。
    • item: 循環體中的具體對象。支持屬性的點路徑訪問,如 item.age,item.info.details。具體說明:在 list 和數組中是其中的對象,在 map 中是 value,該參數為必選。(它是每一個元素進行迭代時的別名)
    • index:在 list 和數組中,index 是元素的序號;在 map 中,index 是元素的 key。
    • open:表示該語句以什么開始
    • close:表示該語句以什么結束
    • separator:表示在每次進行迭代之間以什么符號作為分隔符

補充

 在insert時使用foreach批量插入

insert into user(id,name)
values
<foreach collection="list" separator=","  item="item" index="index">
        (#{item.id},#{item.name})
</foreach>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM