MyBatis批量插入大量數(shù)據(jù)(1w以上)
問題背景:只用MyBatis中foreach進(jìn)行批量插入數(shù)據(jù),一次性插入超過一千條的時(shí)候MyBatis開始報(bào)錯(cuò)。項(xiàng)目使用技術(shù):SpringBoot、MyBatis
批量插入碰到的問題:
java.lang.StackOverflowError: null
該問題是由于一次性插入數(shù)據(jù)1w條引起的,具體插入代碼如下:
userDao.batchInsert(list); <insert id="batchInsert" parameterType="java.util.List"> ? ? INSERT INTO USER ? ? <trim prefix="(" suffix=")" suffixOverrides=","> ? ? ? ? ID, AGE, NAME, EMAIL ? ? </trim> ? ? SELECT A.* ? ? FROM ? ? (<foreach collection="list" index="index" item="item" separator="UNION ALL"> ? ? SELECT ? ? sys_guid(), #{user.age}, #{user.name}, #{user.email} ? ? FROM dual </foreach>) A </insert>
以上的插入代碼其實(shí)也是一種批量插入的方式,但是他的靈界點(diǎn)并不高,插入數(shù)據(jù)過多的時(shí)候,可能需要我們使用代碼在一次分批。當(dāng)然如果插入數(shù)據(jù)不超過5000的時(shí)候可以直接這么使用
插入1w條數(shù)據(jù),發(fā)現(xiàn)出現(xiàn)錯(cuò)誤,原因是數(shù)據(jù)量過大,棧內(nèi)存溢出了。mybatis中直接使用foreach插入數(shù)據(jù),就相當(dāng)于將所有的sql預(yù)先拼接到一起,然后一起提交。這本身就是一種批量插入的處理方案,但是達(dá)不到我們要求。主要是插入有上限。如果需要更多的數(shù)據(jù)導(dǎo)入,我們需要更換一種方式來解決這個(gè)問題,mybatis中ExecutorType的使用。
mybatis中ExecutorType的使用
Mybatis內(nèi)置的ExecutorType有3種,SIMPLE、REUSE、BATCH; 默認(rèn)的是simple,該模式下它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句,單條提交sql;而batch模式重復(fù)使用已經(jīng)預(yù)處理的語(yǔ)句,并且批量執(zhí)行所有更新語(yǔ)句,顯然batch性能將更優(yōu);但batch模式也有自己的問題,比如在Insert操作時(shí),在事務(wù)沒有提交之前,是沒有辦法獲取到自增的id,這在某型情形下是不符合業(yè)務(wù)要求的;
插入大量數(shù)據(jù)的解決方案,使用ExecutorType
為了能夠高效,并且解決上述問題,我們使用ExecutorType,并分批插入。代碼如下:
//我們使用的是springboot,sqlSessionTemplate是可以自己注入的 @Autowired private SqlSessionTemplate sqlSessionTemplate; public void insertExcelData(List<User> list) { ? ? //如果自動(dòng)提交設(shè)置為true,將無法控制提交的條數(shù),改為最后統(tǒng)一提交,可能導(dǎo)致內(nèi)存溢出 ? ? SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); ? ? //不自動(dòng)提交 ? ? try { ? ? ? ? UserDao userDao = session.getMapper(UserDao.class); ? ? ? ? for (int i = 0; i < list.size(); i++) { ? ? ? ? ? ? userDao.insert(list.get(i)); ? ? ? ? ? ? if (i % 400 == 0 || i == list.size() - 1) { ? ? ? ? ? ? ? ? //手動(dòng)每400條提交一次,提交后無法回滾 ? ? ? ? ? ? ? ? session.commit(); ? ? ? ? ? ? ? ? //清理緩存,防止溢出 ? ? ? ? ? ? ? ? session.clearCache(); ? ? ? ? ? ? } ? ? ? ? } ? ? } catch (Exception e) { ? ? ? ? //沒有提交的數(shù)據(jù)可以回滾 ? ? ? ? session.rollback(); ? ? } finally { ? ? ? ? session.close(); ? ? } } userDao.insert(User user); <insert id="insert" parameterType="com.echo.UserPo"> ? ? insert into USER ? ? (id ? ? <if test="age != null"> ? ? ? ? ,age ? ? </if> ? ? <if test="name != null"> ? ? ? ? ,name ? ? </if> ? ? <if test="email != null"> ? ? ? ? ,email ? ? </if> ? ? ) ? ? values ( ? ? sys_guid() ? ? <if test="age != null"> ? ? ? ? ,#{age} ? ? </if> ? ? <if test="name != null"> ? ? ? ? ,#{name} ? ? </if> ? ? <if test="email != null"> ? ? ? ? ,#{email} ? ? </if>) </insert>
這里采用的是單條插入,直接使用for循環(huán),但是使用ExecutorType.BACTH就相當(dāng)于手動(dòng)提交。這也是我們需要的效果,所以我們?cè)谘h(huán)里面判斷了,是否到了第400筆,如果到了第400筆就直接提交,然后清空緩存,防止溢出。這樣就有效的實(shí)現(xiàn)了批量插入,同時(shí)保證溢出問題的不出現(xiàn)
到此這篇關(guān)于MyBatis批量插入大量數(shù)據(jù)(1w以上)的文章就介紹到這了,更多相關(guān)MyBatis批量插入內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mybatis和mybatisplus批量插入問題示例詳解
- MyBatis-plus批量插入的通用方法使用
- Mybatis批量插入大量數(shù)據(jù)的最優(yōu)方式總結(jié)
- Mybatis-Plus批量插入用法詳解
- 使用Mybatis的Batch?Insert?Support?實(shí)現(xiàn)批量插入
- Mybatis批量插入index out of range錯(cuò)誤的解決(較偏的錯(cuò)誤)
- mybatis實(shí)現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)
- Mybatis-plus 批量插入太慢的問題解決(提升插入性能)
- MyBatis批量插入的五種方式
相關(guān)文章
SpringMVC中事務(wù)是否可以加在Controller層的問題
這篇文章主要介紹了SpringMVC中事務(wù)是否可以加在Controller層的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02詳解SpringBoot時(shí)間參數(shù)處理完整解決方案
這篇文章主要介紹了詳解SpringBoot時(shí)間參數(shù)處理完整解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Druid(新版starter)在SpringBoot下的使用教程
Druid是Java語(yǔ)言中最好的數(shù)據(jù)庫(kù)連接池,Druid能夠提供強(qiáng)大的監(jiān)控和擴(kuò)展功能,DruidDataSource支持的數(shù)據(jù)庫(kù),這篇文章主要介紹了Druid(新版starter)在SpringBoot下的使用,需要的朋友可以參考下2023-05-05java使用renderer將pdf按頁(yè)轉(zhuǎn)換為圖片
這篇文章主要為大家詳細(xì)介紹了java使用renderer將pdf按頁(yè)轉(zhuǎn)換為圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12如何禁用IntelliJ IDEA的LightEdit模式(推薦)
這篇文章主要介紹了如何禁用IntelliJ IDEA的LightEdit模式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Java游戲服務(wù)器系列之Netty相關(guān)知識(shí)總結(jié)
今天帶大家來學(xué)習(xí)Java游戲服務(wù)器的相關(guān)知識(shí),文中對(duì)Netty作了非常詳細(xì)的介紹,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05