You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Data JPA:如何让表存储多条同ID记录不被覆盖?

问题根源与解决方案

问题出在第二张表的主键设计上:你把SALE_ID设成了SECONDTABLE的主键,而主键的唯一性约束导致同一SALE_ID只能存在一条记录,后续插入同ID的记录会被判定为更新操作,直接覆盖之前的数据。


具体解决步骤

1. 修改第二张表的数据库结构

给SECONDTABLE添加一个独立的主键字段(比如UUID或自增ID),将SALE_ID改为普通外键关联第一张表:

create or replace SECONDTABLE (
    ID VARCHAR(100) NOT NULL DEFAULT UUID_STRING() COMMENT '独立主键',
    SALE_ID VARCHAR(100) NOT NULL COMMENT '关联第一张表的销售ID',
    -- 其他字段...
    PRIMARY KEY (ID),
    FOREIGN KEY (SALE_ID) REFERENCES FIRSTTABLE(SALE_ID)
);

2. 更新第二张表的实体类

修改实体类的主键注解,新增外键关联字段:

@Entity
@Table(name = "SECONDTABLE")
public class SecondTableEntity {
    // 独立主键
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    @JdbcTypeCode(SqlTypes.VARCHAR)
    private UUID id;

    // 关联第一张表的外键
    @Column(name = "SALE_ID")
    @JdbcTypeCode(SqlTypes.VARCHAR)
    private UUID saleId;

    // 其他字段、getter/setter、builder方法...
}

3. 调整服务层代码

构建SecondTableEntity时,把第一张表的ID赋值给saleId字段(而非原来的主键id):

public ReturnDto save(InputDto inputDto) {
    FirstTableEntity a = FirstTableEntity.builder()
        // 填充第一张表的字段
        .build();
    FirstTableEntity savedA = repo1.save(a);

    List<SecondTableEntity> secondList = inputDto.getArrayOfString().stream()
        .map(e -> SecondTableEntity.builder()
            .saleId(savedA.getId()) // 赋值给外键字段
            // 填充第二张表的其他字段
            .build())
        .collect(Collectors.toList());

    repo2.saveAll(secondList);
    // 构建返回结果
    return ReturnDto.builder().build();
}

为什么之前会出现覆盖?

Spring Data JPA中,save()/saveAll()方法会根据主键判断执行逻辑:

  • 若实体主键值在库中不存在,执行插入;
  • 若主键值已存在,执行更新(覆盖原有记录)。

你之前把SALE_ID作为SECONDTABLE的主键,数组中每个元素生成的实体都用同一个SALE_ID作为主键,JPA会将后续实体判定为对同一条记录的更新,最终只保留最后一条数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:40:05