mysql批量保存或者更新可以极大地减少网络调用,提升性能。
批量保存是将多条数据组装成 insert into xxx (xx,yy) values (xx1,yy1),(xx2,yy2)的方式。
批量更新是将多条数据组装成update xx set t=t1,g=g1 where s1=1;update xx set t=t2,g=g2 where s1=2;的方式。
JdbcTemplate提供了很好用的批量保存或者更新的方法,只需要提供SQL语句和设置相应参数的方法即可。
public void batchSave(List<SomeModel> someModels) {
if(CollectionUtil.isEmpty(someModels)){
return;
}
int batchCount = someModels.size() / batchSize + 1;
for (int i = 0; i < batchCount; i++) {
List<SomeModels> list = List2Page.toPage(someModelss, i + 1, batchSize).getList();
if(CollectionUtil.notEmpty(list)){
logger.info("第 " + (i+1) + " 次 " + list.size());
saveInBatch(list);
}
}
}
private int[] saveInBatch(List<SomeModel> someModels) {
return jdbcTemplate.batchUpdate(SAVE_SQL, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
SomeModel someModel = someModels.get(i);
////调用PreparedStatement的相应参数设置方法,注意从1开始
}
@Override
public int getBatchSize() {
return someModels.size();
}
});
}
要注意几个问题,
1. 对于保存来说,是无法获取到自增主键的,对于JdbcTemplate全部返回的是-2(根据JDBC 2.0规范,值为-2表示操作成功,但受影响的行数是未知的)。如果需要,可以通过设置一个批次号,保存之后再通过批次号查询出来。
2. 需要在jdbc URL中添加一个参数才支持批量
rewriteBatchedStatements=true
3. mysql是有sql语句长度限制的,默认为1M。 所以一次保存或者更新的条数也不能太大。可以通过max_allowed_packet修改。
List2Page.toPage完成内存分页,可以很好地处理第三个问题,其来自 https://gitee.com/xxssyyyyssxx/utils
Jfinal的Db+Record也提供了批量处理方法,如果二者都不想引入,可以自己按照以上说明的两种模式生成SQL语句。