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.
This is not possible. The foreign key can not refer to part of composite primary key of other table. Because it is supposed to be one-to-one relationship and if you refer just part of primary-key, there might be more than one parent record available, which is neither allowed nor possible.
A table can have only one Primary Key. A table can have any number of Foreign Keys. The primary key is unique and Not Null. A foreign key can contain duplicate values also.
You can use JPA's @MapsId annotation to tell Hibernate that it shall use the foreign key of an associated entity as the primary key. Let's take a look at a simple example. Each Book has a Manuscript, and each Manuscript belongs to 1 Book. The foreign key of the Book is also the primary key of the Manuscript.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With