JPA / Hibernate,@ OneToMany和约束(Oracle)

时间:2011-08-25 20:04:15

标签: hibernate jpa foreign-keys constraints

我有以下情况:

@Entity
class A {

  @Id
  @GeneratedValue
  private long dbId;

  @OneToMany ( cascade = CascadeType.ALL )
  @JoinColumn( name = "A_ID", referencedColumnName = "DBID" )
  Set<C> setOfCs;

}

@Entity
class B {

  @Id
  @GeneratedValue
  private long dbId;

  @OneToMany ( cascade = CascadeType.ALL )
  @JoinColumn( name = "B_ID", referencedColumnName = "DBID" )
  Set<C> setOfCs;

}

@Entity
class C {

    @Id
@GeneratedValue
private long dbId;

}

创建表C时,两列A_ID和B_ID分别作为A.DBID和B.DBID的外键。这在我的情况下没有多大意义,因为C的每个元素都是从A或(xor)B链接而不是同时链接(两个关系都是一对多而不是多对多)。

有没有办法在A_ID和B_ID上没有外键约束的情况下拥有相同的表(没问题)?当我设置A-> C时,Oracle抱怨没有设置C.B_ID。

由于

利玛

2 个答案:

答案 0 :(得分:1)

为什么不使用@JoinTable?它将删除表C上的任何外键。

@OneToMany(cascade = CascadeType.ALL,fetch=FetchType.LAZY,orphanRemoval=true)
@JoinTable(name = "A_B_TABLE", joinColumns = { @JoinColumn(name = "A_ID") },      inverseJoinColumns = { @JoinColumn(name = "DB_ID") })
public Set<C> getSetOfCs() {
    return setOfCs;
}

顺便说一下,不要注释项目,而是在其getter上进行注释。

答案 1 :(得分:0)

我能想到的唯一方法是通过一个公共类强制这两种关系,C可以有一个外键。

最简单的方法是引入一些类X,它将是A和B的超类,并且具有dbId和setOfCs属性。然后,C表将有一列X_ID。

或者,使C抽象,并引入子类Ca和Cb,这样A的实例总是引用Ca的实例,B实例引用Cb的实例。 Ca和Cb中的每一个只需要一个外键。但是,这可能非常难以使用;除其他外,这意味着你永远不能将C的实例从A转移到B。

如果你不能介绍任何基类,你可以在一个间接层上应用Wheeler's law和石膏,结合上述两种方法。创建一个抽象类X,并从A和B为它提供dbId和setOfCs属性; C然后有一个幻像ManyToOne关系到X,它的表有相应的外键。创建X,Xa和Xb的两个具体子类,每个子类分别与A或B的实例具有OneToOne关系,A和B的实例具有指向另一个方向的相应OneToOne关系。