spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼
有3種實(shí)現(xiàn)方式:foreach,spring事務(wù),以及ExecutorType.BATCH.
1. foreach方式
這種方式實(shí)際是對(duì)SQL語(yǔ)句進(jìn)行拼接,生成一個(gè)長(zhǎng)長(zhǎng)的SQL,對(duì)很多變量進(jìn)行綁定。如果數(shù)據(jù)量不大(1000個(gè)以?xún)?nèi)),可以用這種方式。如果數(shù)據(jù)量太大,可能數(shù)據(jù)庫(kù)會(huì)報(bào)錯(cuò)。
定義接口
public interface StudentMapper05 {
public void insertStudent(List<Student> studentList);
}
定義mapper
適用于Oracle數(shù)據(jù)庫(kù)
<insert id="insertStudent">
BEGIN
<foreach collection="list" item="student" index="index" separator="">
INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL)
VALUES
(SEQ_ID.nextval, #{student.name}, #{student.branch}, #{student.percentage}, #{student.phone}, #{student.email});
</foreach>
END;
</insert>
這個(gè)mapper的含義,就是把上送的studentList拼接成一個(gè)長(zhǎng)SQL,拼成的SQL類(lèi)似:
BEGIN INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?); INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?); INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?); ... END;
studentList有幾個(gè),就會(huì)生成多少個(gè)insert語(yǔ)句拼接到一起,每個(gè)?都會(huì)進(jìn)行變量綁定,所以當(dāng)studentList中數(shù)據(jù)量較多時(shí),生成的SQL會(huì)很長(zhǎng),導(dǎo)致數(shù)據(jù)庫(kù)執(zhí)行報(bào)錯(cuò)。
dao
public class StudentDao05 {
private StudentMapper05 studentMapper; // 省略getter和setter
public void insertStudentList(List<Student> studentList) {
studentMapper.insertStudent(studentList);
}
}
beans
mybatis-spring-05.xml:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="oracleDataSource" /> <property name="configLocation" value="classpath:mybatis/config/mybatis-config-05.xml"/> </bean> <bean id="studentMapper05" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper05" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> <bean id="studentDao05" class="com.ws.experiment.spring.mybatis.dao.StudentDao05"> <property name="studentMapper" ref="studentMapper05" /> </bean>
main函數(shù)
public static void main(String[] args) {
String[] configFiles = new String[]{"spring-beans-config.xml", "mybatis/mybatis-spring-05.xml"}; // 分別配置datasource和mybatis相關(guān)bean
ApplicationContext context = new ClassPathXmlApplicationContext(configFiles);
StudentDao05 studentDao = (StudentDao05)context.getBean("studentDao05");
int counts[] = new int[]{10, 50, 100, 200, 500, 1000, 2000, 3000, 5000, 8000};
for (int count : counts) {
List<Student> studentList = new ArrayList<>();
for (int i = 0; i < count; i++) {
Student st = new Student();
st.setName("name");
st.setBranch("");
st.setEmail("");
st.setPercentage(0);
st.setPhone(0);
studentList.add(st);
}
long startTime = System.currentTimeMillis();
studentDao.insertStudentList(studentList);
long endTime = System.currentTimeMillis();
System.out.println("插入" + count + "筆數(shù)據(jù)耗時(shí): " + (endTime - startTime) +" ms");
}
}
測(cè)試結(jié)果
插入100筆數(shù)據(jù)耗時(shí): 197 ms
插入200筆數(shù)據(jù)耗時(shí): 232 ms
插入500筆數(shù)據(jù)耗時(shí): 421 ms
插入1000筆數(shù)據(jù)耗時(shí): 650 ms
插入2000筆數(shù)據(jù)耗時(shí): 1140 ms
插入3000筆數(shù)據(jù)耗時(shí): 27113 ms
插入5000筆數(shù)據(jù)耗時(shí): 98213 ms
插入8000筆數(shù)據(jù)耗時(shí): 301101 ms
2. 借助spring事務(wù)
借助spring事務(wù),插入一組數(shù)據(jù)
開(kāi)啟spring事務(wù)
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="oracleDataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" />
定義接口
public interface StudentMapper06 {
public void insertStudent(@Param("student") Student student);
}
mapper
<insert id="insertStudent">
INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL)
VALUES
(SEQ_ID.nextval, #{student.name}, #{student.branch}, #{student.percentage}, #{student.phone}, #{student.email})
</insert>
dao
public class StudentDao06 {
private StudentMapper06 studentMapper; // 省略getter和setter
@Transactional // spring事務(wù)控制
public void insertStudentList(List<Student> students) {
for (Student student : students) {
studentMapper.insertStudent(student);
}
}
}
beans
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="oracleDataSource" /> <property name="configLocation" value="classpath:mybatis/config/mybatis-config-06.xml"/> </bean> <bean id="studentMapper06" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> <bean id="studentDao06" class="com.ws.experiment.spring.mybatis.dao.StudentDao06"> <property name="studentMapper" ref="studentMapper06" /> </bean>
main
略
測(cè)試結(jié)果
batchInsert001插入10筆數(shù)據(jù)耗時(shí): 602 ms
batchInsert001插入50筆數(shù)據(jù)耗時(shí): 196 ms
batchInsert001插入100筆數(shù)據(jù)耗時(shí): 284 ms
batchInsert001插入200筆數(shù)據(jù)耗時(shí): 438 ms
batchInsert001插入500筆數(shù)據(jù)耗時(shí): 944 ms
batchInsert001插入1000筆數(shù)據(jù)耗時(shí): 1689 ms
batchInsert001插入2000筆數(shù)據(jù)耗時(shí): 3138 ms
batchInsert001插入3000筆數(shù)據(jù)耗時(shí): 4427 ms
batchInsert001插入5000筆數(shù)據(jù)耗時(shí): 7368 ms
batchInsert001插入8000筆數(shù)據(jù)耗時(shí): 11832 ms
3. 使用ExecutorType.BATCH
基本原理是SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);,設(shè)置BATCH方式的sqlSession
有三種設(shè)置方式:
3.1 在mybatis的config文件中設(shè)置
SqlSessionFactoryBean中可以配置配置文件:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="oracleDataSource" /> <property name="configLocation" value="classpath:mybatis/config/mybatis-config-06.xml"/> </bean>
這個(gè)mybatis配置文件中,設(shè)置BATCH方式:
<configuration>
<settings>
<!-- 默認(rèn)打開(kāi)BATCH的Executor -->
<setting name="defaultExecutorType" value="BATCH" />
</settings>
<mappers>
<mapper class="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" />
</mappers>
</configuration>
這樣,默認(rèn)打開(kāi)的sqlSession就都是BATCH方式的。再與spring的事務(wù)結(jié)合(參看上一節(jié)中的spring事務(wù)設(shè)置),就可以實(shí)現(xiàn)批量插入。
測(cè)試結(jié)果:
batchInsert001插入10筆數(shù)據(jù)耗時(shí): 565 ms
batchInsert001插入50筆數(shù)據(jù)耗時(shí): 117 ms
batchInsert001插入100筆數(shù)據(jù)耗時(shí): 98 ms
batchInsert001插入200筆數(shù)據(jù)耗時(shí): 106 ms
batchInsert001插入500筆數(shù)據(jù)耗時(shí): 145 ms
batchInsert001插入1000筆數(shù)據(jù)耗時(shí): 132 ms
batchInsert001插入2000筆數(shù)據(jù)耗時(shí): 154 ms
batchInsert001插入3000筆數(shù)據(jù)耗時(shí): 163 ms
batchInsert001插入5000筆數(shù)據(jù)耗時(shí): 200 ms
batchInsert001插入8000筆數(shù)據(jù)耗時(shí): 250 ms
3.2 自己創(chuàng)建sqlSession,手工commit
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory)context.getBean("sqlSessionFactory");
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
StudentMapper06 studentMapper = sqlSession.getMapper(StudentMapper06.class);
for (int i = 0; i < count; i++) {
Student st = new Student();
st.setName("name");
...
studentMapper.insertStudent(st);
}
sqlSession.commit();
sqlSession.clearCache();
sqlSession.close();
測(cè)試結(jié)果:
batchInsert002插入10筆數(shù)據(jù)耗時(shí): 568 ms
batchInsert002插入50筆數(shù)據(jù)耗時(shí): 157 ms
batchInsert002插入100筆數(shù)據(jù)耗時(shí): 132 ms
batchInsert002插入200筆數(shù)據(jù)耗時(shí): 135 ms
batchInsert002插入500筆數(shù)據(jù)耗時(shí): 148 ms
batchInsert002插入1000筆數(shù)據(jù)耗時(shí): 139 ms
batchInsert002插入2000筆數(shù)據(jù)耗時(shí): 151 ms
batchInsert002插入3000筆數(shù)據(jù)耗時(shí): 139 ms
batchInsert002插入5000筆數(shù)據(jù)耗時(shí): 207 ms
batchInsert002插入8000筆數(shù)據(jù)耗時(shí): 299 ms
3.3 使用sqlSessionTemplate在XML文件中創(chuàng)建bean
創(chuàng)建一個(gè)SqlSessionTemplate,然后注入到MapperFactoryBean中,生成對(duì)應(yīng)的mapper:
<!-- 以ExecutorType.BATCH方式插入數(shù)據(jù)庫(kù) --> <bean id="batchSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /> <constructor-arg name="executorType" value="BATCH" /> </bean> <bean id="studentMapper06_batch" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" /> <property name="sqlSessionTemplate" ref="batchSqlSessionTemplate" /> </bean> <bean id="studentDao06_batch" class="com.ws.experiment.spring.mybatis.dao.StudentDao06"> <property name="studentMapper" ref="studentMapper06_batch" /> </bean>
與spring的事務(wù)結(jié)合后(參看上一節(jié)中的spring事務(wù)設(shè)置),就可以實(shí)現(xiàn)批量插入
測(cè)試結(jié)果
batchInsert003插入10筆數(shù)據(jù)耗時(shí): 651 ms
batchInsert003插入50筆數(shù)據(jù)耗時(shí): 133 ms
batchInsert003插入100筆數(shù)據(jù)耗時(shí): 124 ms
batchInsert003插入200筆數(shù)據(jù)耗時(shí): 129 ms
batchInsert003插入500筆數(shù)據(jù)耗時(shí): 144 ms
batchInsert003插入1000筆數(shù)據(jù)耗時(shí): 179 ms
batchInsert003插入2000筆數(shù)據(jù)耗時(shí): 229 ms
batchInsert003插入3000筆數(shù)據(jù)耗時(shí): 241 ms
batchInsert003插入5000筆數(shù)據(jù)耗時(shí): 216 ms
batchInsert003插入8000筆數(shù)據(jù)耗時(shí): 259 ms
到此這篇關(guān)于spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼的文章就介紹到這了,更多相關(guān)spring mybatis批量插入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mybatis中批量插入的兩種方式(高效插入)
- MyBatis批量插入(insert)數(shù)據(jù)操作
- Mybatis中使用updateBatch進(jìn)行批量更新
- Mybatis批量修改的操作代碼
- 詳解mybatis 批量更新數(shù)據(jù)兩種方法效率對(duì)比
- mybatis執(zhí)行批量更新batch update 的方法(oracle,mysql兩種)
- MyBatis批量添加、修改和刪除
- Mybatis批量刪除多表
- Mybatis 插入一條或批量插入 返回帶有自增長(zhǎng)主鍵記錄的實(shí)例
- MyBatis批量插入數(shù)據(jù)到Oracle數(shù)據(jù)庫(kù)中的兩種方式(實(shí)例代碼)
- Mybatis批量更新報(bào)錯(cuò)問(wèn)題
- Mybatis批量更新三種方式的實(shí)現(xiàn)
相關(guān)文章
java微信掃描公眾號(hào)二維碼實(shí)現(xiàn)登陸功能
這篇文章主要為大家詳細(xì)介紹了PHP微信掃描公眾號(hào)二維碼實(shí)現(xiàn)登陸功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Springboot 使用具體化類(lèi)和配置來(lái)縮短單元測(cè)試時(shí)間
這篇文章主要介紹了Springboot 使用具體化類(lèi)和配置來(lái)縮短單元測(cè)試時(shí)間,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java之如何正確地對(duì)包裝類(lèi)進(jìn)行裝箱與拆箱
在這篇文章中給大家繼續(xù)講解包裝類(lèi)的裝箱和拆箱問(wèn)題。你可能會(huì)很好奇,做java開(kāi)發(fā),怎么還裝起箱子來(lái)了?那么就請(qǐng)大家?guī)е苫笸驴窗?/div> 2023-04-04
Java源碼深度分析String與StringBuffer及StringBuilder詳解
當(dāng)對(duì)字符串進(jìn)行修改的時(shí)候,需要使用?StringBuffer?和?StringBuilder類(lèi),和String類(lèi)不同的是,StringBuffer和?StringBuilder類(lèi)的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象,本篇我們來(lái)分析分析它們的源碼2022-05-05
Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解
這篇文章主要為大家?介紹了Springboot遷移到Micronaut實(shí)現(xiàn)過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
mybatisplus實(shí)現(xiàn)自動(dòng)填充時(shí)間的項(xiàng)目實(shí)踐
在數(shù)據(jù)庫(kù)操作中,頻繁設(shè)置創(chuàng)建時(shí)間和更新時(shí)間字段非常繁瑣,通過(guò)使用MyBatis-Plus的自動(dòng)填充功能,可以簡(jiǎn)化操作,本文就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下2024-10-10
淺談Java多線(xiàn)程處理中Future的妙用(附源碼)
這篇文章主要介紹了淺談Java多線(xiàn)程處理中Future的妙用(附源碼),還是比較不錯(cuò)的,需要的朋友可以參考下。2017-10-10
java文件操作練習(xí)代碼 讀取某個(gè)盤(pán)符下的文件
這篇文章主要介紹了java讀取某個(gè)盤(pán)符下的文件示例,代碼中要求的是絕對(duì)路徑,編譯過(guò)程中要注意絕對(duì)路徑問(wèn)題和異常的抓取2014-01-01最新評(píng)論

