#为什么强调springcloud(springboot)框架?因为本文中,并没有对mybatis做配置改变。即使用了springboot零配置的特性。
在实际开发中,经常遇到大数据量的插入,比如导入excel,每行数据转换都是一条model,很容易出现几千上万条数据的导入。
解决大数据量插入且快速响应,有以下两种方式:
1、(文件解析成功后)将大数据量的插入任务扔给后台,告诉前端已经操作成功,稍后刷新页面。。
方法1:通过MQ扔给schedule定时器去执行插入任务
方法2:开启另一个Thread执行插入任务
2、想办法提升插入效率。
本文说明的是第二种方式,提升插入效率的办法。
springcloud(springboot)+mybatis框架下,代码结构是:mapper(java/xml)-->service(interface/impl)-->biz(interface/impl)
1、修改jdbcUrl,增加参数rewriteBatchedStatements=true使之能满足批量插入:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://${db.host}:${db.port}/${db.schema}?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.datasource.username=${db.username}
spring.datasource.password=${db.password}
2、在bizImpl内完成了数据组装(从excel或其他文档中读取数据,组装成List<T>),调用service接口方法batchInsertByExecutor实现数据插入。
3、service接口类创建一个批量插入的接口方法:
boolean batchInsertByExecutor(List<T> list);
4、serviceImpl实现service的批量插入接口方法:
(1)下方代码中,T是泛指某实体类,具体业务需要替换成具体的实体类。
(2)此方法中的内容都有注释,说明的比较清楚。比如为什么批量插入的方法,调用的是Mapper的单条插入方法,注释都有解释。
(3)此方法是在service层创建了一个批量插入的方法,没有改变Mapper和biz,也没有改变其他方法的数据插入方式和调用方式,因此不用担心其他的数据插入方法受影响。
(4)此方法利用ExecutorType.BATCH提交数据,满足数据回滚。即在bizImpl中调用此方法后,再抛出异常,此方法内插入的数据将回滚。
/**
** 注入SqlSessionFactory,通过它创建session
*/
@Autowired
private SqlSessionFactory factory;
@Override
public boolean batchInsertByExecutor(List<T> list) {
// 1、设置ExecutorType.BATCH批量模式:
// (1.1)把SQL语句发给数据库,数据库预编译好,数据库等待需要运行的参数,接收到参数后一次运行;
// (1.2)ExecutorType.BATCH只打印一次SQL语句,多次设置参数步骤,
// 2、设置autoCommit=false,改为手动提交事务
SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false);
try {
// 每次手动提交事务时,批次已插入数据量。如1000条一次提交。
int batchSize = 1000;
int size = list.size();
TMapper tMapper = sqlSession.getMapper(TMapper.class);
for (int i = 0; i < size; i++) {
// 调用单条插入,而非batchInsert。
// 原因:ExecutorType.BATCH+insert并非直接插入,而是数据库预编译,等待事务提交
T model = list.get(i);
tMapper.insert(model);
// 批次提交事务
if (i > 0 && i % batchSize == 0) {
// 预插入,代替commit()和closeCache()
sqlSession.flushStatements();
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
sqlSession.rollback();
} finally {
// 关闭事务
sqlSession.close();
}
return false;
}
以上就是批量插入的方法。基于springcloud(springboot)+mybatis(也可以是mybaits-plus),不改变mapper、biz(restful业务接口层),只在service创建一个独立的插入方法即可。
测试结果:
本人在实际项目中使用BATCH方法数据插入,包含文档解析等业务处理过程:
(1)4K+条数据插入,前端调用响应约1秒;
(2)1W+条数据插入,前端调用响应约2秒。