jpa批量处理

2,738 阅读1分钟

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条1138ms13071ms
10000条2687ms88523ms