Hibernate Spring Data JPA批量更新前如何避免每条实体单独执行select查询
Spring Data JPA 脱管实体批量更新避免N次查询解决方案
方案1:批量获取持久态代理对象关联
该方案无需修改原有业务逻辑,仅调整实体关联逻辑即可避免单条查询:
- 首先从所有待更新的脱管实体中提取主键ID集合
- 调用
JpaRepository.getReferenceById()(旧版本为getOne())批量获取对应ID的持久态代理,该方法不会立刻触发数据库查询 - 遍历将脱管实体中需要更新的字段手动赋值到对应的代理对象上
- 最后调用
saveAll()提交更新,此时仅会执行批量更新语句,不会额外触发单条SELECT查询
适用场景:每个实体的更新规则不统一,需要执行自定义业务逻辑后再更新的场景
方案2:直接执行JPQL批量更新语句
性能最高的方案,全程无额外SELECT查询:
你可以直接在Repository层自定义批量更新的JPQL语句,示例如下:
@Modifying @Query("update 你的实体类 e set e.待更新字段1 = :value1, e.待更新字段2 = :value2 where e.id in :ids") int batchUpdateFields(@Param("ids") List<Long> 主键ID集合, @Param("value1") Object 字段值1, @Param("value2") Object 字段值2);
适用场景:所有待更新实体的更新规则统一,不需要触发Hibernate实体生命周期回调、不需要更新缓存的场景
方案3:开启Hibernate批量抓取优化
如果业务逻辑要求必须先加载完整实体再更新,可以开启批量抓取减少查询次数:
- 在对应实体类上添加
@BatchSize(size = 100)注解,原本10000次单条SELECT会被合并为100次批量查询 - 也可以全局配置
hibernate.default_batch_fetch_size = 100,对所有实体生效
适用场景:需要加载完整实体执行复杂业务逻辑,且无法用前两种方案优化的场景
通用批量操作优化配置
无论使用哪种方案,都建议添加以下配置开启Hibernate原生批量提交能力,进一步提升性能:
spring: jpa: properties: hibernate: jdbc: batch_size: 100 # 每100条SQL合并为一次批量提交 order_inserts: true # 排序插入语句,优化批量提交效率 order_updates: true # 排序更新语句,优化批量提交效率 batch_versioned_data: true # 支持带@Version注解的乐观锁实体批量更新
内容的提问来源于stack exchange,提问作者erdem
相关产品推荐
相关产品推荐

