假如需要搬一萬塊磚到樓頂,有一部電梯足绅,電梯一次可以放適量的磚(最多放 500)捷绑。可以選擇一次運送一塊磚氢妈,也可以一次運送 500 塊磚粹污,哪個時間消耗大?
一、sql 層面實現(xiàn)數(shù)據(jù)插入
- 單條插入數(shù)據(jù)的寫法:
insert into table ([列名],[列名]) values ([列值],[列值]));
或:
insert into table values ([列值],[列值]));
- 批量插入
一種可以在代碼中循環(huán)執(zhí)行上面的語句首量,但是這種效率太差壮吩。另一種,可以用 MySQL 支持的批量插入語句加缘,這種方式更高效鸭叙。
insert into table ([列名],[列名])
VALUES
([列值],[列值]),
([列值],[列值]),
([列值],[列值]);
批量的好處:可以避免程序和數(shù)據(jù)庫建立多次連接,增加服務器負荷拣宏。
二沈贝、MyBatis 層面批量插入數(shù)據(jù)到數(shù)據(jù)庫
兩種方式:xml 文件和注解。使用批量插入執(zhí)行的 sql 語句應該等價于:
insert into table (id, name,sex,address)
values
(?,?,?,?),(?,?,?,?),(?,?,?,?),(?,?,?,?)
1??xml 配置
最基礎的是用 mapping.xml 配置的方式勋乾,包括以下兩種具體方式:
- mapping.xml 中 insert 語句可以寫成單條插入宋下,在調(diào)用方循環(huán) 1000 次
<!-- 在外部for循環(huán)調(diào)用1000次 -->
<insert id="insert" parameterType="com.xxp.mybatis.Person">
insert into person (id, name,sex,address)
values
(#{id,jdbcType=INTEGER},#{name,jdbcType=VARCHAR},
#{sex,jdbcType=VARCHAR},#{address,jdbcType=VARCHAR})
</insert>
- mapping.xml 中 insert 語句寫成一次性插入一個 1000 的 list
<insert id="insertBatch" >
insert into person ( <include refid="Base_Column_List" /> )
values
<foreach collection="list" item="item" index="index" separator=",">
(null,#{item.name},#{item.sex},#{item.address})
</foreach>
</insert>
參數(shù)解釋:
foreach 的主要作用在構建 in 條件中,它可以在 sql 語句中進行迭代一個集合辑莫。foreach 元素的屬性主要有 collection学歧,item,separator各吨,index枝笨,open,close。
collection:指定要遍歷的集合横浑。表示傳入過來的參數(shù)的數(shù)據(jù)類型剔桨。該屬性是必須指定的,要做 foreach 的對象徙融。在使用 foreach 的時候最關鍵的也是最容易出錯的就是 collection 屬性领炫。在不同情況 下,該屬性的值是不一樣的张咳,主要有一下 3 種情況:
a. 如果傳入的是單參數(shù)且參數(shù)類型是一個 List 的時候,collection 屬性值為 list似舵。
b. 如果傳入的是單參數(shù)且參數(shù)類型是一個數(shù)組的時候脚猾,collection 的屬性值為 array。
c. 如果傳入的參數(shù)是多個的時候砚哗,就需要把它們封裝成 Map龙助,當然單參數(shù)也可以封裝成 Map。Map 對象沒有默認的鍵蛛芥。item:表示集合中每一個元素進行迭代時的別名提鸟。將當前遍歷出的元素賦值給指定的變量,然后用#{變量名}仅淑,就能取出變量的值称勋,也就是當前遍歷出的元素。
separator:表示在每次進行迭代之間以什么符號作為分隔符涯竟。
select * from tab where id in(1,2,3)
相當于1,2,3之間的","index:索引赡鲜。index 指定一個名字,用于表示在迭代過程中庐船,每次迭代到的位置银酬。遍歷 list 的時候 index 就是索引,遍歷 map 的時候 index 表示的就是 map 的 key筐钟,item 就是 map 的值揩瞪。
open/close:表示該語句以什么開始/結束。
mapper 接口中的使用:
public interface TabMapper {
public List<Tab> getTabsByConditionLike(@Param("list")List<Integer> ids);
}
2??注解
MyBatis 提供用于插入數(shù)據(jù)的注解有兩個:@insert篓冲,@InsertProvider李破。類似還有:@DeleteProvider、@UpdateProvider和@SelectProvider纹因。
作用:
用來在實體類的 Mapper 類里注解保存方法的 sql 語句喷屋。
區(qū)別:
@Insert 是直接配置 sql 語句,而 @InsertProvider 則是通過 sql 工廠類及對應的方法生產(chǎn) sql 語句瞭恰,這種方法的好處在于屯曹,可以根據(jù)不同的需求生產(chǎn)出不同的 sql,適用性更好。
使用:
@Insert("insert into blog(blogId,title,author) values(#blogId,#title,#author)")
public boolean saveBlog(Blog blog);
@InsertProvider
在 mapper 接口中的方法上使用 @InsertProvider 注解:
參數(shù)解釋:
type 為工廠類的類對象恶耽,
method 為對應的工廠類中的方法密任,方法中的 @Param(“l(fā)ist”) 是因為批量插入傳入的是一個 list,但是 Mybatis 會將其包裝成一個 map偷俭。其中 map 的 key 為“l(fā)ist”浪讳,value為傳入的 list。
三涌萤、xml/注解 兩種方式的區(qū)別
1??foreach 相當語句逐條 insert 語句執(zhí)行淹遵,將出現(xiàn)如下問題:
- mapper 接口的 insert 方法返回值將是最后一條 insert 語句的操作成功的記錄數(shù)目(就是0或1),而不是所有 insert 語句的操作成功的總記錄數(shù)目负溪;
- 當其中一條不成功時透揣,不會進行整體回滾。
2??注解方式:當有一條插入不成功時川抡,會整體回滾辐真。