Spring Boot中OneToMany关联返回重复数据且缺失部分数据问题
Kit关联KitImage查询重复且缺失问题排查修复
问题描述
开发Spring Boot项目时,Kit实体与KitImage实体为一对多关联,使用findAll查询Kit时,Kit数据正常,但关联的图片出现异常:图片数量正确,但所有图片均为第一条数据的重复,同时存在部分图片缺失。
错误根源分析
KitImage实体主键设计错误
原KitImage仅将kitId标注为@Id,同时数据库表用(kit_id, image)作为复合主键。但Hibernate仅识别@Id标注的字段作为实体唯一标识,导致同一个Kit下的所有KitImage被判定为同一实例,最终重复加载第一条数据。另外,byte[]类型的image不适合作为主键,数据库层面无法正确区分不同图片,导致重复图片无法插入,出现缺失。数据库迁移脚本错误
kit_image表中kit_id设置了DEFAULT public.gen_random_uuid(),这完全错误,kit_id应该是关联kits表的外键,而非自动生成新UUID,导致外键关联逻辑混乱。同时复合主键包含image字段,不合理且无法正确工作。实体映射逻辑错误
使用@MapsId但主键仅为kitId,不符合一对多关联的映射规范,导致Hibernate无法正确区分不同的KitImage实例。
修复步骤
1. 修改KitImage实体代码
给KitImage添加独立主键,修正映射逻辑:
@Entity @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE) @Table(name = "kit_image") public class KitImage { @Id @GeneratedValue private UUID id; // 新增独立主键 @NonNull @JsonBackReference @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "kit_id", referencedColumnName = "id") Kit kit; // 去掉@MapsId,因为现在有独立主键 byte[] image; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; KitImage kitImage = (KitImage) o; return Objects.equals(id, kitImage.id); } @Override public int hashCode() { return Objects.hash(id); } }
2. 修改数据库迁移脚本
修正kit_image表的结构,添加独立主键,移除错误的默认值和不合理的复合主键:
CREATE TABLE kits ( id uuid DEFAULT public.gen_random_uuid(), name TEXT NOT NULL, description TEXT, link TEXT NOT NULL, quantity INTEGER NOT NULL default 0, quantity_lent INTEGER NOT NULL default 0, quantity_reserved INTEGER NOT NULL default 0, pdf bytea, PRIMARY KEY (id) ); CREATE TABLE kit_image ( id uuid DEFAULT public.gen_random_uuid(), kit_id uuid NOT NULL, image bytea, PRIMARY KEY (id), FOREIGN KEY (kit_id) REFERENCES kits(id) );
3. 验证修复
重新执行数据库迁移,启动项目后使用findAll查询Kit,此时关联的KitImage会正确加载所有不同的图片,不会出现重复和缺失问题。
内容的提问来源于stack exchange,提问作者Symtox
相关产品推荐
相关产品推荐

