处理记录
借鉴文章地址:https://www.imooc.com/article/321536
采用方案:for 循环循环插入
JDBC 中的 PreparedStatement 有预编译功能,预编译之后会缓存起来,后面的 SQL 执行会比较快并且 JDBC 可以开启批处理,这个批处理执行非常快。
具体步骤:
1.设置MySQL批量执行
MySQL JDBC 驱动在默认情况下会无视 executeBatch() 语句,把我们期望批量执行的一组 sql 语句拆散,一条一条地发给 MySQL 数据库,批量插入实际上是单条插入,直接造成较低的性能。将 rewriteBatchedStatements 参数置为 true, 数据库驱动才会帮我们批量执行 SQL。
2.开启批处理 ExecutorType.BATCH
@Transactional(rollbackFor = Exception.class)
public List<StudentBatchImportDto> studentBatchImport(List<StudentBatchImportDto> read, Map collects, Map map) {
//如果自动提交设置为true,将无法控制提交的条数,改为最后统一提交。
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
MicroApplicationMapper sessionMapper = session.getMapper(MicroApplicationMapper.class);
Date date = new Date();
String pwd = passwordEncoder.encode(DEFAULT_PASSWORD);
//用来装重复数据
List<StudentBatchImportDto> list = new ArrayList<>();
int dateSize = read.size();
int i =1;
for (StudentBatchImportDto studentBatchImportDto : read) {
//如果身份证已存在则不导入
String ifExit = (String)collects.get(studentBatchImportDto.getIdCard());
if(!StringUtils.isEmpty(ifExit)){//判断当前身份证是否在数据库存在
list.add(studentBatchImportDto);
}else {
//插入表t_user
studentBatchImportDto.setPwd(pwd);
studentBatchImportDto.setDate(date);
sessionMapper.insertStudentSource(studentBatchImportDto);
if(i % size ==0){ //防止内存溢出,分批提交
session.commit();
}
i++;
}
}
session.commit();
return list;
}
虽然是一条一条的插入,但是开启了批处理模式(BATCH),这样前前后后就只用这一个 SqlSession。节约了反反复复获取 Connection 以及释放 Connection 得大量时间。
最后插入15000大概2.6M得数据大概花了1-2秒左右得时间。