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

复合主键ManyToMany映射出现重复列映射异常求助

问题:复合主键下ManyToMany映射出现重复列错误

错误信息

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Repeated column in mapping for collection: com.abc.reports.entities.Packages.protectedItems column: account_id

相关代码

复合主键类

@Embeddable
@Getter
@Setter
@ToString
public class PackageId implements Serializable {

    private String accountId;

    private Long packageId;

}

@Embeddable
@Getter
@Setter
@ToString
public class ProtectedItemsId implements Serializable {

    private String accountId;

    private Long protectedItemId;

}

实体类

Packages.class

@Entity
@Getter
@Setter
@ToString
public class Packages {

    @EmbeddedId
    private PackageId packageId;

    private String packageName;

    @ManyToMany(mappedBy = "packageItemsList")
    @JsonIgnore
    private List<ProtectedItems> protectedItems;
    
}

ProtectedItems.class

@Entity
@Getter
@Setter
public class ProtectedItems implements Serializable {

    @EmbeddedId
    private ProtectedItemsId protectedItemId;

    private String protectedItemName;

    @ManyToMany
    @JoinTable(
            name="jt_packages_protected_items",
            joinColumns = {@JoinColumn(name="accountId", insertable=false, updatable=false), @JoinColumn(name="protectedItemId", insertable=false, updatable=false)},
            inverseJoinColumns = {@JoinColumn(name="accountId", insertable=false, updatable=false), @JoinColumn(name="packageId", insertable=false, updatable=false)} )
    private List<Packages> packageItemsList;

    @ManyToMany(mappedBy = "protectedItemsList")
    @JsonIgnore
    private List<StreamMappings> streamMappings;

    @Override
    public String toString() {
        return "ProtectedItems{" +
                "protectedItemId=" + protectedItemId +
                ", protectedItemName='" + protectedItemName +
                ", packageItemsList=" + packageItemsList.hashCode() +
                ", streamMappings=" + streamMappings +
                '}';
    }
}

问题原因与解决方法

核心原因

错误根源在于ProtectedItems类的@JoinTable注解中,joinColumns和inverseJoinColumns同时映射了accountId列,导致Hibernate认为关联表jt_packages_protected_items中的account_id被重复绑定,触发重复列映射异常。

由于两个实体的复合主键都包含accountId,关联表中该字段是共享的,只需在一侧映射即可关联两边的账户维度。

修复步骤

  1. 修改ProtectedItems中的@JoinTable配置,移除inverseJoinColumns中的accountId映射:
@ManyToMany
@JoinTable(
        name="jt_packages_protected_items",
        joinColumns = {
                @JoinColumn(name="accountId", referencedColumnName="accountId", insertable=false, updatable=false),
                @JoinColumn(name="protectedItemId", referencedColumnName="protectedItemId", insertable=false, updatable=false)
        },
        inverseJoinColumns = {
                @JoinColumn(name="packageId", referencedColumnName="packageId", insertable=false, updatable=false)
        } )
private List<Packages> packageItemsList;
  1. 补充复合主键类的equals()和hashCode()方法(Hibernate处理复合主键的必要条件,避免潜在的实体识别问题):
    以PackageId为例:
@Embeddable
@Getter
@Setter
@ToString
public class PackageId implements Serializable {

    private String accountId;

    private Long packageId;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PackageId packageId1 = (PackageId) o;
        return Objects.equals(accountId, packageId1.accountId) && Objects.equals(packageId, packageId1.packageId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accountId, packageId);
    }
}

同理给ProtectedItemsId添加相同逻辑的equals()和hashCode()方法。

说明

关联表jt_packages_protected_items的结构应包含三个字段:accountId、protectedItemId、packageId,通过accountId关联两个实体的账户维度,protectedItemId和packageId分别关联对应实体的主键字段,这样既保证了关联关系的正确性,又避免了重复列映射的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:49:14