You need to enable JavaScript to run this app. Hibernate原生查询批量插入OneToMany关联数据及返回ID问题
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate原生查询批量插入OneToMany关联数据及返回ID问题

问题1:插入后获取自增ID报错解决

你使用的是SQL Server数据库,默认INSERT语句不会返回结果集,所以调用getSingleResult会抛出异常。要返回自增主键需要在INSERT语句中添加OUTPUT INSERTED.主键列名子句,同时禁止直接拼接SQL防止注入风险,正确写法如下:

// pack_group表本身不存在packArticles字段,该关联关系是通过子表的外键维护的,所以插入语句不需要加该字段
String query = "insert into pack_group(packing_nr, description, qty, delivered_time) " +
        "OUTPUT INSERTED.id " +
        "values (?, ?, ?, ?)";
Query q = entityManager.createNativeQuery(query);
// 按顺序绑定参数,不要用String.format拼接
q.setParameter(1, packGroup.getPackingNr());
q.setParameter(2, packGroup.getDescription());
q.setParameter(3, packGroup.getQty());
q.setParameter(4, packGroup.getDeliveredTime());
Long id = ((Number) q.getSingleResult()).longValue();

问题2:批量保存关联数据的实现方案

推荐优先使用JPA自带批量配置,实现成本低性能达标,如有特殊要求再用原生SQL方案。

方案1:JPA批量插入配置(推荐)

无需修改现有业务逻辑,仅需添加配置即可开启批量插入,性能提升非常明显:

  1. 新增JPA配置(application.yml为例)
spring:
  jpa:
    properties:
      hibernate:
        jdbc:
          batch_size: 500 # 每累积500条语句批量执行一次,可根据实际情况调整
          order_inserts: true # 按实体类型排序插入语句,满足批量执行要求
          order_updates: true
        generate_statistics: false # 调试时可开启,能在日志中查看批量执行效果
  1. 业务逻辑调整为批量保存
// 先组装所有父实体和关联的子实体
List<PackGroupEntity> allGroups = new ArrayList<>();
for (Map.Entry<Integer, List<RecivedArticlesDTO>> entry : groupedArticles.entrySet()) {
    PackGroupEntity packGroup = new PackGroupEntity();
    packGroup.setPackingNr(entry.getKey());
    // 其他父类字段赋值逻辑
    List<PackArticlesEntity> listWithArticles = new ArrayList<>();
    entry.getValue().forEach(pack -> {
        PackArticlesEntity packArticle = new PackArticlesEntity();
        packArticle.setQty(pack.getQty());
        packArticle.setPackGroup(packGroup); // 手动绑定父实体,避免外键为空
        // 其他子类字段赋值逻辑
        listWithArticles.add(packArticle);
    });
    packGroup.setPackArticles(listWithArticles);
    allGroups.add(packGroup);
}
// 一次性保存所有父实体,因为配置了级联保存,子实体会自动批量插入
packGroupRepository.saveAll(allGroups);

方案2:原生SQL批量实现

如果必须用原生SQL实现,步骤如下:

  1. 先批量插入所有PackGroupEntity,通过OUTPUT子句一次性返回所有生成的主键ID,建立packingNr和主键ID的映射关系
  2. 给所有PackArticlesEntity绑定对应的父实体ID,再批量插入所有子实体
    SQL Server批量插入支持多值写法,性能更高:
-- 批量插入父实体并返回主键
INSERT INTO pack_group(packing_nr, description, qty, delivered_time)
OUTPUT INSERTED.id, INSERTED.packing_nr
VALUES (?,?,?,?), (?,?,?,?), (?,?,?,?) -- 按batch_size拼接多组值

内容的提问来源于stack exchange,提问作者xarqt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 12:24:03