使用JoinColumn两次使CompositeKey获得重复列异常

时间:2013-01-29 14:35:18

标签: java hibernate jpa jpa-2.0

我有以下情况:

我正在尝试在一个数据库中构建一个具有相同租户的多租户应用程序 用同样的表。据我所知,Hibernate在5.0之前不支持这个变种。

我试图通过在每个表中添加brandId字段来解决这个问题。

当我构建Many To Many关系时,我还将这个brandId添加到ManyToMany Join Table和这里(不知道我是否可以这样做,mysql没有抱怨)我为两个表创建了一个外键,同时包括brandid < / p>

所以现在例如我有一个表Text(ID,name,brandId)和一个Tag(ID,name,brandId)和一个连接表(text_id,tag_id,brand_id),其中外键是

CONSTRAINT FK_TAG_TEXTS_TAG FOREIGN KEY (TAG_ID,BRAND_ID) REFERENCES TAG (ID,brand),

CONSTRAINT FK_TAG_TEXTS_TEXT FOREIGN KEY (TEXT_ID,BRAND_ID) REFERENCES TEXT (ID,brand)

正如您所见,品牌ID被使用了两次。

然后我使用Hibernate Tools生成了我的类,它创建了一个复合主键类,以及Tag类中的关联。

  @ManyToMany(fetch = FetchType.EAGER,cascade = {CascadeType.PERSIST,CascadeType.MERGE })
  @JoinTable(name = "tag_texts", , joinColumns = {
    @JoinColumn(name = "TAG_ID", nullable = false, insertable = false, updatable = false),
    @JoinColumn(name = "BRAND_ID", nullable = false, insertable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "TEXT_ID", insertable = false, nullable = false, updatable = false),@JoinColumn( name = "BRAND_ID",  insertable = false, nullable = false, updatable = false) })
public List<Text> getTexts() {
    return this.texts;
}

现在的问题是我得到以下异常:

  

org.hibernate.MappingException:集合映射中的重复列:de.company.domain.Tag.texts column:brand_id

我查看了Collection类中的Hibernate代码,它引发了异常。 这里调用方法'checkColumnDupliation',它使用Set并插入名称, 这意味着第二次将“BRAND_ID”作为列插入会导致此行为。

我发现重复列错误最常见的解决方案是在多个引用中使用相同的列时插入'insertable = false和updateable = false'。这在这里描述:
Hibernate: Where do insertable = false, updatable = false belong in composite primary key constellations involving foreign keys?

但这似乎与我的问题不同。

所以我的问题是:是否有可能使用JPA Annotations解决这个问题,并在joinColumns和inverseJoinColumns中使用品牌ID?

1 个答案:

答案 0 :(得分:0)

问题是您需要3个实体之间的JoinTable:TextTagBrand

可能你必须使用 IdClass ,例如:

public class AssociationId implements Serializable {
  private long textId;
  private long tagId;
  private long brandId;

  hash and equals function
  ...
}

Id类实体:

@Entity
@Table(name="tag_text_brand")
@IdClass(AssociationId.class)
public class TagTextBrandAssociation {
  @Id
  private long tagId;
  @Id
  private long textId;
  @Id
  private long textId;

  @ManyToOne
  @PrimaryKeyJoinColumn(name="TAG_ID", referencedColumnName="ID")
  private Tag tag;
  @ManyToOne
  @PrimaryKeyJoinColumn(name="TEXT_ID", referencedColumnName="ID")
  private Text text;
  @ManyToOne
  @PrimaryKeyJoinColumn(name="BRAND_ID", referencedColumnName="ID")
  private Brand brand;
  ...
}

您可以在3个实体中使用此功能:

@Entity
public class Text {
  @Id
  private long id;
  ...
  @OneToMany(mappedBy="text")
  private List<TagTextBrandAssociation> tagsAndBrands;
  ...
}

有关详细信息,请参阅here