JPA/Hibernate, @OneToMany and constraints (Oracle)
I have the following scenario:
@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;
}
Table C is created with two columns A_ID and B_ID as foreign keys to A.DBID and B.DBID respectively. This makes little sense in my case as each element of C is either linked f开发者_Python百科rom A or (xor) B but not both at the same time (both relationships are one-to-many not many-to-many).
Is there a way to have the same tables (which are fine) without the foreign key constraint on A_ID and B_ID? When I set A->C Oracle complains that C.B_ID is not set.
Thanks
Matteo
Why don't you use @JoinTable? it will remove any foreign key on table 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;
}
and by the way do not annotate items, do it on its getters instead.
The only way i can think of to do this is to force both relationships through a common class, to which C can have a foreign key.
The simplest way to do this would be to introduce some class X which would be a superclass of A and B, and would have the dbId and setOfCs properties. C's table would then have a column X_ID.
Alternatively, make C abstract, and introduce subclasses Ca and Cb, such that instances of A always referred to instances of Ca, and instances of B to Cb. Each of Ca and Cb would only need a single foreign key. This might be very awkward to use, though; amongst other things, it would mean you could never transfer an instance of C from an A to a B.
If you weren't in a position to introduce any base classes, you could apply Wheeler's law and plaster on a layer of indirection, combining both the above approaches. Create an abstract class X, and give it the dbId and setOfCs properties from A and B; C then has a phantom ManyToOne relationship to X, and it table has the corresponding foreign key. Create two concrete subclasses of X, Xa and Xb, each having a OneToOne relationship with an instance of A or B respectively, those instances of A and B having corresponding OneToOne relationships pointing in the other direction.
精彩评论