最近开发的时候遇到一个问题,需要一次插入一千多条数据怎么写?
最开始我是这么写的
public void xxxService(List<DTO> list){
for(DTO dto : list) {
mapper.insert(dto);
}
}
简化了一下,大概是这个意思,然后前端插数据等了五分钟控制台还在刷,真的难绷,笑死我了,我都在想我怎么会写出这种代码。
之后我发现了mp继承IService有加强功能,里面就有批量插入的方法叫saveBatch()
然后我这么写
List<MtyTaskCompanyDO> list = taskCompany.stream()
.map(s -> {
MtyTaskCompanyDO companyDO = new MtyTaskCompanyDO();
companyDO.setId(UUID.randomUUID().toString());
companyDO.setCompanyId(s);
companyDO.setTaskId(taskId);
return companyDO;
})
.collect(Collectors.toList());
saveBatch(list);
这样写我以为完美了,让前端去试,结果发现还是很慢,一直没有响应。很无奈,于是我找了找原因,我们看看源码。
default boolean saveBatch(Collection<T> entityList) {
return this.saveBatch(entityList, 1000);
}
这里没什么问题,我们接着进
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
int size = entityList.size();
executeBatch(sqlSession -> {
int i = 1;
for (T entity : entityList) {
sqlSession.insert(sqlStatement, entity);
if ((i % batchSize == 0) || i == size) {
sqlSession.flushStatements();
}
i++;
}
});
return true;
}
好,发现问题所在了,原来源码也在循环,真的难绷,可能相对于循环插入快一点,但也快不到哪里去,所以还得是让mybatis出马。
最后我这样写
mp中不写xml的方式,自己拼接sql语句,这样比较原始
@Resource
JdbcTemplate template;
StringBuilder sqlFormat = new StringBuilder("inset into mty_task_company (id, taskId, companyId) values ");
for(int i = 0; i < taskCompany.size(); i++){
sqlFormat.append("(").append(UUID.randomUUID()).append(",").append(taskId).append(",").append(taskCompany.get(i)).append(")");
if(i != taskCompany.size()-1){
sqlFormat.append(",");
}
}
template.execute(sqlFormat.toString());
第二种就自己写xml咯,我推荐这种
<!-- 批量写入 -->
<insert id="batchInsert">
INSERT INTO mty_task_company(
id, task_id, company_id
)VALUES
<foreach collection="list" item="item" index="index" separator="," >
(
#{item.id},#{item.taskId},#{item.companyId}
)
</foreach>
</insert>