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
相关产品推荐
相关产品推荐

