Mybatis批量插入或更新數據


對於大量的數據,使用批量插入或修改可以提高效率。原因是批量添加或修改是執行一條sql語句,傳入多個值,可以減少與數據庫的訪問次數,從而會提高效率。下面分別介紹Oracle和MySQL的用法:

1.Oracle批量插入數據

對於集合類型的數據,在插入時會使用mybatis的<foreach>標簽,那么正確的用法如下:

<insert id="insertUserBatch">
insert into user(id,name,password,addr)
select user_seq.nextval,a.* from(
<foreach collection="list" item="item" open="(" close=")" separator="union all">
select
#{item.name},
#{item.password},
#{item.addr}
from dual
</foreach>
) a
</insert>

以上語句是向user表循環查詢數據,傳遞的參數是List<User>類型的集合。

需要注意是的,在使用時,分隔符separator必須是union all。

2.MySQL批量插入數據

對於集合類型的數據,在插入時會使用mybatis的<foreach>標簽,那么mysql的批量插入數據sql如下:

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

和oracle的語句相比,沒有指定主鍵,原因是主鍵id使用了自增。在foreach中里面的兩個括號不能省略,要使用逗號作為分隔符。

3.Mybatis的trim標簽

3.1功能屬性表

trim標簽的功能屬性如下表:

屬性名 說明
prefix 在sql語句前面拼接的字符串
suffix 在sql語句后面拼接的字符串
prefixOverrides 去除sql語句前面指定的字符或者關鍵字
suffixOverrides 去除sql語句后面指定的字符或者關鍵字

3.2去除多余的and關鍵字

1)先看下面最原始的sql:

<select id="findActiveBlogLike">
  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

2)這種sql肯定會導致異常的出現。如果僅僅第二個條件匹配,那么這條 SQL 最終的樣子:

SELECT * FROM BLOG
WHERE 
AND title like '%aaa%'

這種sql就多了一個and關鍵字,也會導致異常的發生。

3)對於mybatis而言,可以使用where標簽來解決上述的問題,其sql如下:

<select id="findActiveBlogLike">
  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 like #{author}
    </if>
  </where>
</select>

4)除此之外,mybatis還提供了另一個標簽trim,可以用其來去除多余的關鍵字,上一步的代碼使用trim如下:

<select id="findActiveBlogLike">
  SELECT * FROM BLOG 
  <trim prefix="WHERE" prefixOverrides="AND">
    <if test="state != null">
      state = #{state}
    </if> 
    <if test="title != null">
      AND title like #{title}
    </if>
    <if test="author != null">
      AND author like #{author}
    </if>
  </trim>
</select>

上述的sql中,當條件中沒有匹配的數據時,不會添加where關鍵字;當匹配到條件時,會在前面拼接where關鍵字,若匹配的條件前面有and,那么會自動去掉and關鍵字。舉例說明,條件的內容只作為說明:

A:當state、title、author都為NULL時,查詢語句是

SELECT * FROM BLOG 

B:當title、author都為NULL而state不為NULL時,查詢語句是:

SELECT * FROM BLOG
where state = 1

C:當state、author都為NULL而title不為NULL時,去除了多余的and關鍵字,查詢語句是:

SELECT * FROM BLOG
where title like '%aaa%'

D:當state、title都不為NULL而author為NULL時,查詢語句是:

SELECT * FROM BLOG
where state = 1
and title like '%aaa%'

3.3去除多余的逗號

 1)先看下面的sql:

<insert id="insertBlogSelective">
  insert into BLOG 
  (  
    <if test="state != null">
         state</if> 
    <if test="title != null">
        title,
    </if>
    <if test="author != null">
        author
    </if>
   )
   values(
    <if test="state != null">
        #{state},
    </if> 
    <if test="title != null">
        #{title},
    </if>
    <if test="author != null">
        #{author}
    </if>
   )
</insert >

若這些條件中author沒有匹配上,那么這條 SQL 會變成:

insert into BLOG(state,title,) values(1,'mysql入門',);

明顯看出多了兩個逗號,會導致異常。使用trim標簽解決如下:

<insert id="insertBlogSelective">
  insert into BLOG 
  <trim prefix="(" suffix=")" suffixOverrides=",">  
    <if test="state != null">
         state
    </if> 
    <if test="title != null">
        title,
    </if>
    <if test="author != null">
        author
    </if>
   </trim>
   <trim prefix="values(" suffix=")" suffixOverrides=",">  
    <if test="state != null">
        #{state},
    </if> 
    <if test="title != null">
        #{title},
    </if>
    <if test="author != null">
        #{author}
    </if>
   </trim>
</insert >

上述的sql中,當條件中沒有匹配的數據時,不會插入對應的列數據。主要是使用suffixOverrides屬性,當條件不滿足時會刪除結尾多余的逗號。

4.Oracle批量修改數據

 當數據量很大時,使用批量修改可以提高效率。看下面對用戶信息進行批量修改:

   <update id="updateBatch">
        update user t
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="name  = case" suffix="end ,">
                <foreach collection="list" item="item">
                    <if test="item.name != null ">
                        when t.id = #{item.id} then #{item.name}
                    </if>
                </foreach>
            </trim>
            <trim prefix="password  = case" suffix="end ,">
                <foreach collection="list" item="item">
                    <if test="item.password != null ">
                        when t.id = #{item.id} then #{item.password}
                    </if>
                </foreach>
            </trim>
            <trim prefix="addr  = case" suffix="end ,">
                <foreach collection="list" item="item">
                    <if test="item.addr != null ">
                        when t.id = #{item.id} then #{item.addr}
                    </if>
                </foreach>
            </trim>
        </trim>
        where id in
        <foreach collection="list" item="item" open="(" close=")" separator=",">
            #{item.id}
        </foreach>
    </update>

使用了trim標簽,生成的完整的sql如下,為了說明方便僅對三條數據進行修改,批量的數據是類似的:

update user t set 
  name = case 
     when t.id = ? then ? 
     when t.id = ? then ? 
     when t.id = ? then ? end , 
  password = case 
         when t.id = ? then ? 
         when t.id = ? then ? 
         when t.id = ? then ? end , 
  addr = case 
     when t.id = ? then ? 
     when t.id = ? then ?
     when t.id = ? then ? end 
where id in ( ? , ? , ? )

在上述的sql中,使用了兩層的trim標簽,外層的標簽添加了前綴"set"關鍵字,另外如果有多余的逗號則會刪除。內層的trim對應一個字段,當此字段不為null時才會包含內部的代碼;也使用了case when關鍵字。下面對幾種情況進行分析:

A:name為NULL,其他屬性不為NULL時,實際的語句如下:

update user t set 
  password = case 
         when t.id = ? then ? 
         when t.id = ? then ? 
         when t.id = ? then ? end , 
  addr = case 
     when t.id = ? then ? 
     when t.id = ? then ?
     when t.id = ? then ? end 
where id in ( ? , ? , ? )

當屬性為NULL時,此字段便不會被添加到sql語句當中,上述這種情況就是很好的說明。

B:password為NULL,其他屬性不為NULL時,實際的語句

update user t set 
  name = case 
     when t.id = ? then ? 
     when t.id = ? then ? 
     when t.id = ? then ? end , 
  addr = case 
     when t.id = ? then ? 
     when t.id = ? then ?
     when t.id = ? then ? end 
where id in ( ? , ? , ? )

C:addr為NULL,其他屬性不為NULL時,實際的語句

update user t set 
  name = case 
     when t.id = ? then ? 
     when t.id = ? then ? 
     when t.id = ? then ? end , 
  password = case 
         when t.id = ? then ? 
         when t.id = ? then ? 
         when t.id = ? then ? end 
where id in ( ? , ? , ? )

由於addr的前面有其他的trim,那么當addr為NULL時,就會自動刪除關鍵字'end"后面的逗號。

5.MySQL批量修改數據

MySQL的修改語法和oracle的語法基本類似,批量修改的語句可直接參考oracle的批量修改。


免責聲明!

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



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