處理記錄
借鑒文章地址:https://www.imooc.com/article/321536
采用方案:for 循環(huán)循環(huán)插入
JDBC 中的 PreparedStatement 有預(yù)編譯功能,預(yù)編譯之后會緩存起來,后面的 SQL 執(zhí)行會比較快并且 JDBC 可以開啟批處理,這個(gè)批處理執(zhí)行非???。
具體步驟:
1.設(shè)置MySQL批量執(zhí)行
MySQL JDBC 驅(qū)動在默認(rèn)情況下會無視 executeBatch() 語句,把我們期望批量執(zhí)行的一組 sql 語句拆散,一條一條地發(fā)給 MySQL 數(shù)據(jù)庫,批量插入實(shí)際上是單條插入,直接造成較低的性能。將 rewriteBatchedStatements 參數(shù)置為 true, 數(shù)據(jù)庫驅(qū)動才會幫我們批量執(zhí)行 SQL。

image.png
2.開啟批處理 ExecutorType.BATCH
@Transactional(rollbackFor = Exception.class)
public List<StudentBatchImportDto> studentBatchImport(List<StudentBatchImportDto> read, Map collects, Map map) {
//如果自動提交設(shè)置為true,將無法控制提交的條數(shù),改為最后統(tǒng)一提交。
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
MicroApplicationMapper sessionMapper = session.getMapper(MicroApplicationMapper.class);
Date date = new Date();
String pwd = passwordEncoder.encode(DEFAULT_PASSWORD);
//用來裝重復(fù)數(shù)據(jù)
List<StudentBatchImportDto> list = new ArrayList<>();
int dateSize = read.size();
int i =1;
for (StudentBatchImportDto studentBatchImportDto : read) {
//如果身份證已存在則不導(dǎo)入
String ifExit = (String)collects.get(studentBatchImportDto.getIdCard());
if(!StringUtils.isEmpty(ifExit)){//判斷當(dāng)前身份證是否在數(shù)據(jù)庫存在
list.add(studentBatchImportDto);
}else {
//插入表t_user
studentBatchImportDto.setPwd(pwd);
studentBatchImportDto.setDate(date);
sessionMapper.insertStudentSource(studentBatchImportDto);
if(i % size ==0){ //防止內(nèi)存溢出,分批提交
session.commit();
}
i++;
}
}
session.commit();
return list;
}
雖然是一條一條的插入,但是開啟了批處理模式(BATCH),這樣前前后后就只用這一個(gè) SqlSession。節(jié)約了反反復(fù)復(fù)獲取 Connection 以及釋放 Connection 得大量時(shí)間。
最后插入15000大概2.6M得數(shù)據(jù)大概花了1-2秒左右得時(shí)間。