I have to work with Hibernate and I am not very sure how to solve this problem, I have 2 tables with a 1..n relationship like this:
-------
TABLE_A
-------
col_b (pk)
col_c (pk)
[other fields]
-------
TABLE_B
-------
col_a (pk)
col_b (pk) (fk TABLE_A.col_b)
col_c (fk TABLE_A.col_c)
[other fields]
How can I manage this with Hibernate?
I do not have any idea how to declare a foreign key that would contain a part of primary key.
My database schema is generated from the Hibernate model.
I have found two solutions to this problem.
The first one is rather a workaround and is not so neat as the second one.
Define the primary key of the B
entity as composite key containing col_a
, col_b
, and col_c
and what was supposed to be the primary key in the first place, define as unique constraint. The disadvantage is that the column col_c
is not really conceptually a part of primary key.
@Entity
class A {
@Id
private int b;
@Id
private int c;
}
@Entity
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "a", "b" }) })
class B {
@Id
private int a;
@Id
@ManyToOne(optional = false)
@JoinColumns(value = {
@JoinColumn(name = "b", referencedColumnName = "b"),
@JoinColumn(name = "c", referencedColumnName = "c") })
private A entityA;
}
The second uses @EmbeddedId
and @MapsId
annotations and does exactly what I wanted to be done at the very beginning.
@Entity
class A {
@Id
private int b;
@Id
private int c;
}
@Embeddable
class BKey {
private int a;
private int b;
}
@Entity
class B {
@EmbeddedId
private BKey primaryKey;
@MapsId("b")
@ManyToOne(optional = false)
@JoinColumns(value = {
@JoinColumn(name = "b", referencedColumnName = "b"),
@JoinColumn(name = "c", referencedColumnName = "c") })
private A entityA;
}
Jagger's second solution that is my first reaction, with @EmbededId and @MapsId. The following is another way based on his second solution but without using @MapsId.
`
@Entity
class A {
@Id
private int b;
@Id
private int c;
}
@Embeddable
class BKey {
private int a;
private int b;
}
@Entity
class B {
@EmbeddedId
private BKey primaryKey;
@ManyToOne(optional = false)
@JoinColumns(value = {
@JoinColumn(name = "b", referencedColumnName = "b", insertable= false, updatable= false),
@JoinColumn(name = "c", referencedColumnName = "c") }, )
private A entityA;
}