我有以下情况:
@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。
由于
利玛
答案 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关系。