對於大量的數據,使用批量插入或修改可以提高效率。原因是批量添加或修改是執行一條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的批量修改。
