jpa批量处理
我们知道jpa提供saveAll处理批量插入,代码如下
public <S extends T> List<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "Entities must not be null!");
List<S> result = new ArrayList<S>();
for (S entity : entities) {
result.add(save(entity));
}
return result;
}
乍一看似乎是一个一个save
其实不然,查看源码(这里不细说),jpa每次save都会先添加到action queue,在flush的时候,再通过insert action构造statement的batch操作,然后到达一个批量的时候才perform,达到一个batch的时候会调用executeBatch()
也就是说,最终还是使用了jdbc statement的executeBatch的调用模式
同理 jdbcTemplate.batchUpdate同样最终也是使用了jdbc的batch
如何使用jpa批量处理
经查阅资料,了解到要使用jpa的批量处理需要在jpa配置:
spring.jpa.properties.hibernate.jdbc.batch_size=500
spring.jpa.properties.hibernate.order_inserts=true
-- 重点是配置rewriteBatchedStatements=true,开启jdbc的批量处理
spring.datasource.url = jdbc:mysql://192.168.240.4:8066/xxx?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true
本着严谨的态度测试:
@Test(description = "批量插入测试saveAll测试 自增主键")// 9968ms 加入jpa配置 9929ms
public void testSaveAll(){
List<ShortUrlQueryRecordEntity> entities = new ArrayList<ShortUrlQueryRecordEntity>();
for (int i =0 ; i<1000; i++){
ShortUrlQueryRecordEntity entity = new ShortUrlQueryRecordEntity();
entity.setCreateTime(new Timestamp(System.currentTimeMillis()));
entity.setIp("119.75.217.109");
entity.setLongUrl("https://baijiahao.baidu.com/");
entities.add(entity);
//shortUrlQueryRecordRepository.save(shortUrlQueryRecordEntity);
}
shortUrlQueryRecordRepository.saveAll(entities);
}
发现使用jpa批量配置和不使用的结果分别为9929ms、9968ms,基本无差距
那么是为什么呢?
经过大量的google发现
当主键生成策略为GenerationType.IDENTITY时,hibernate在jdbc级别禁用批量插入
相关stackoverflow看这里:
stackoverflow.com/questions/2…
使用uuid
这里我们使用uuid作为id,首先将配置修改为
测试用例:
@Test(description = "批量插入测试saveAll测试 uuid")//
public void testCopySaveAll(){
List<ShortUrlQueryRecordCopyEntity> entities = new ArrayList<>();
for (int i =0 ; i<10000; i++){
ShortUrlQueryRecordCopyEntity entity = new ShortUrlQueryRecordCopyEntity();
entity.setCreateTime(new Timestamp(System.currentTimeMillis()));
entity.setIp("119.75.217.109");
entity.setLongUrl("https://baijiahao.baidu.com/");
entities.add(entity);
}
shortUrlQueryRecordCopyRepository.saveAll(entities);
}
测试结果对比
测试结果 | 加了jpa批量配置 | 没加 |
---|---|---|
1000条 | 1138ms | 13071ms |
10000条 | 2687ms | 88523ms |