JPA: difference between @JoinColumn and @PrimaryKeyJoinColumn?

Viewed 118061

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?

4 Answers

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.

You use @JoinColumn when you want to manage (change the column name, set nullable and so on) the foreign key column in the target entity table. Here, the Address table will contains User table id like foreign key but the column it's will be name user_id (the second scheme of @Sam YC)

@Entity
public class Address implements Serializable {

@Id
@GeneratedValue
private String id;

private String city;

@OneToOne(optional = false)
@JoinColumn(name = "user_id", updatable = false)
private User user;
}

You use @PrimaryKeyJoinColumn, when you want to use the primary key of the referencing entity like the target entity primary key. Here the Address know the referencing User but Address table hasn't foreign key column, because it's Id the same like User Id (the first scheme of @Sam YC)

@Entity
public class Address implements Serializable {

@Id
@GeneratedValue(generator = "foreignKeyGenerator")
@GenericGenerator(
        name = "foreignKeyGenerator",
        strategy = "foreign",
        parameters = @org.hibernate.annotations.Parameter(
                name = "property", value = "userT"
        )
)
private String id;
private String city;

@OneToOne(optional = false)
@PrimaryKeyJoinColumn
private User userT;
}
Related