JPA: difference between @JoinColumn and @PrimaryKeyJoinColumn?
JavaHibernateJpaJakarta EeIdentifying RelationshipJava Problem Overview
What's the exact difference between @JoinColumn
and @PrimaryKeyJoinColumn
?
You use @JoinColumn
for columns that are part of a foreign key. A typical column could look like (e.g. in a join table with additional attributes):
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;
What happens if I promote the column to be a/the PK, too (a.k.a. identifying relationship)? As the column is now the PK, I must tag it with @Id
:
@Id
@ManyToOne
@JoinColumn(name = "...")
private OtherClass oc;
Now the question is:
Are @Id
+ @JoinColumn
the same as just @PrimaryKeyJoinColumn
?:
@ManyToOne
@PrimaryKeyJoinColumn(name = "...")
private OtherClass oc;
If not, what's @PrimaryKeyJoinColumn
there for?
Java Solutions
Solution 1 - Java
> What happens if I promote the column to be a/the PK, too (a.k.a. identifying relationship)? As the column is now the PK, I must tag it with @Id (...).
This enhanced support of derived identifiers is actually part of the new stuff in JPA 2.0 (see the section 2.4.1 Primary Keys Corresponding to Derived Identities in the JPA 2.0 specification), JPA 1.0 doesn't allow Id
on a OneToOne
or ManyToOne
. With JPA 1.0, you'd have to use PrimaryKeyJoinColumn
and also define a Basic
Id
mapping for the foreign key column.
> Now the question is: are @Id + @JoinColumn the same as just @PrimaryKeyJoinColumn?
You can obtain a similar result but using an Id
on OneToOne
or ManyToOne
is much simpler and is the preferred way to map derived identifiers with JPA 2.0. PrimaryKeyJoinColumn
might still be used in a JOINED inheritance strategy. Below the relevant section from the JPA 2.0 specification:
> ### 11.1.40 PrimaryKeyJoinColumn Annotation
>
> The PrimaryKeyJoinColumn
annotation
> specifies a primary key column that is
> used as a foreign key to join to
> another table.
>
> The PrimaryKeyJoinColumn
annotation
> is used to join the primary table of
> an entity subclass in the JOINED
> mapping strategy to the primary table
> of its superclass; it is used within a
> SecondaryTable
annotation to join a
> secondary table to a primary table;
> and it may be used in a OneToOne
> mapping in which the primary key of
> the referencing entity is used as a
> foreign key to the referenced
> entity[108].
>
> ...
>
> If no PrimaryKeyJoinColumn
> annotation is specified for a subclass
> in the JOINED mapping strategy, the
> foreign key columns are assumed to
> have the same names as the primary key
> columns of the primary table of the
> superclass.
>
> ...
>
> Example: Customer and ValuedCustomer subclass
>
> @Entity
> @Table(name="CUST")
> @Inheritance(strategy=JOINED)
> @DiscriminatorValue("CUST")
> public class Customer { ... }
>
> @Entity
> @Table(name="VCUST")
> @DiscriminatorValue("VCUST")
> @PrimaryKeyJoinColumn(name="CUST_ID")
> public class ValuedCustomer extends Customer { ... }
>
> [108] The derived id mechanisms
> described in section 2.4.1.1 are now
> to be preferred over
> PrimaryKeyJoinColumn
for the
> OneToOne mapping case.
See also
> This source http://weblogs.java.net/blog/felipegaucho/archive/2009/10/24/jpa-join-table-additional-state states that using @ManyToOne and @Id works with JPA 1.x. Who's correct now?
The author is using a pre release JPA 2.0 compliant version of EclipseLink (version 2.0.0-M7 at the time of the article) to write an article about JPA 1.0(!). This article is misleading, the author is using something that is NOT part of JPA 1.0.
For the record, support of Id
on OneToOne
and ManyToOne
has been added in EclipseLink 1.1 (see this message from James Sutherland, EclipseLink comitter and main contributor of the Java Persistence wiki book). But let me insist, this is NOT part of JPA 1.0.
Solution 2 - Java
Solution 3 - Java
I know this is an old post, but a good time to use PrimaryKeyColumn
would be if you wanted a unidirectional relationship or had multiple tables all sharing the same id.
In general this is a bad idea and it would be better to use foreign key relationships with JoinColumn
.
Having said that, if you are working on an older database that used a system like this then that would be a good time to use it.