JPA多JoinColumns关联非主键列出现顺序错误问题求助
JPA多字段关联冲突的解决方法
背景与问题
现有三个实体类,结构如下:
// EntityA:attr1与attr2组合唯一 EntityA { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 } // EntityB:attr1与attr2组合唯一 EntityB { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 } // EntityC:attr1与attr2组合不唯一 EntityC { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 }
三个实体的attr1、attr2字段类型完全一致。
尝试在EntityA中通过@JoinColumns分别建立:
- 与
EntityB的@OneToOne非双向关联 - 与
EntityC的@OneToMany非双向关联
配置代码如下:
EntityA { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 @OneToOne(fetch = FetchType.LAZY) @JoinColumns( value = { @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false), @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false) }) EntityB entityB; @OneToMany(fetch = FetchType.LAZY) @JoinColumns( value = { @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false), @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false) }) List<EntityC> entityCList; }
配置后触发报错:
Referenced column 'attr2' mapped by target property 'entityB' occurs out of order in the list of '@JoinColumn's
移除entityB或entityCList任意一个关联后,剩余关联可正常工作。需求为保持非双向关联,直接通过getter获取关联对象,无需编写额外查询语句。
解决方案
这个错误是因为JPA在处理两个基于相同字段的关联映射时,会混淆关联间的列映射关系,以下是两种可行的解决方式:
方案1:使用@AssociationOverrides明确区分关联映射
通过@AssociationOverrides(集合关联也适用)为每个关联指定独立的列映射配置,避免JPA将两个关联的映射规则混淆:
修改后的EntityA代码:
EntityA { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 @OneToOne(fetch = FetchType.LAZY) @AssociationOverrides({ @AssociationOverride( name = "attr1", joinColumns = @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false ) ), @AssociationOverride( name = "attr2", joinColumns = @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false ) ) }) EntityB entityB; @OneToMany(fetch = FetchType.LAZY) @AssociationOverrides({ @AssociationOverride( name = "attr1", joinColumns = @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false ) ), @AssociationOverride( name = "attr2", joinColumns = @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false ) ) }) List<EntityC> entityCList; }
方案2:为关联指定表别名区分映射
给其中一个关联的@JoinColumn显式指定当前表名,让JPA识别为独立的关联映射:
EntityA { - pk(主键) ... - attr1 - attr2 ... 其他唯一属性 @OneToOne(fetch = FetchType.LAZY) @JoinColumns( value = { @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false, table = "entity_a"), // 指定当前表名 @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false, table = "entity_a") }) EntityB entityB; @OneToMany(fetch = FetchType.LAZY) @JoinColumns( value = { @JoinColumn( name = "attr1", referencedColumnName = "attr1", updatable = false, insertable = false), @JoinColumn( name = "attr2", referencedColumnName = "attr2", updatable = false, insertable = false) }) List<EntityC> entityCList; }
两种方案都能保持非双向关联的需求,直接通过getter方法获取关联对象,无需额外编写查询语句。
内容的提问来源于stack exchange,提问作者sz3nt
相关产品推荐
相关产品推荐

