Spring Data JDBC聚合根含多个同类型值对象查询结果异常问题
Spring Data JDBC多同类型关联属性查询返回重复记录问题解决方案
问题根本原因
你的address表仅存储了关联的customer外键,没有字段标识该address记录对应Customer聚合中的address1还是address2属性。Spring Data JDBC查询时会将同一个customer关联的所有address记录做笛卡尔积拼接,2条address记录会生成2*2=4条结果集,映射时就产生了4个ID相同的Customer实例,按ID查询时就会抛出结果大小不符合预期的异常。
当Customer仅包含1个Address属性时,不需要区分属性归属,不会产生笛卡尔积,因此功能正常。
修复方案
方案一:保留address独立表(符合原有设计)
- 改造address表结构,新增用于标识属性归属的字段:
ALTER TABLE "address" ADD COLUMN "address_property" VARCHAR(255) NOT NULL;
- 在Customer类的两个Address属性上添加
@MappedCollection注解,指定关联规则:
import org.springframework.data.relational.core.mapping.MappedCollection; @Data @Builder @AllArgsConstructor class Customer { @Id Long id; String name; @MappedCollection(keyColumn = "address_property", idColumn = "customer") Address address1; @MappedCollection(keyColumn = "address_property", idColumn = "customer") Address address2; }
Spring Data JDBC会自动将属性名address1、address2作为key值存入address_property字段,查询时也会根据该字段区分address对应的属性,避免笛卡尔积问题。
方案二:内嵌Address到Customer表
如果不需要独立存储address,可将Address改为嵌入式对象,无需单独建address表:
- 给Address类添加
@Embeddable注解:
import jakarta.persistence.Embeddable; @Data @Builder @AllArgsConstructor @Embeddable class Address { String city; }
- 改造customer表结构,新增两个address对应的city字段:
ALTER TABLE "customer" ADD COLUMN "address1_city" VARCHAR(255) NOT NULL; ALTER TABLE "customer" ADD COLUMN "address2_city" VARCHAR(255) NOT NULL;
删除原有address表即可,查询时不需要join操作,不会出现重复记录问题。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

