Hibernate Tip: Difference between @JoinColumn and @PrimaryKeyJoinColumn
Take your skills to the next level!
The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, monthly Java Persistence News, monthly coding problems, and regular expert sessions.
Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question for a future Hibernate Tip, please post a comment below.
Question:
Himanshu Srivastava asked today’s question on my YouTube channel:
“What’s the difference between@JoinColumn and @PrimaryKeyJoinColumn?
Also, should we use @PrimaryKeyJoinColumn or @JoinColumn?”
Solution:
The @JoinColumn and the @PrimaryKeyJoinColumn might seem very similar, but they are used in 2 different contexts. You can use the @JoinColumn annotation to map the foreign key column of a managed association. The @PrimaryKeyJoinColumn specifies the mapping of the foreign key column of a secondary table or the foreign key column in an inheritance mapping that uses the JOINED strategy.
So, the annotation you need to use depends on the context in which you want to customize the mapping of the foreign key column. Let’s take a look at an example mapping for both annotations.
Using the @JoinColumn annotation
When you add the @JoinColumn annotation to your association mapping, you can define the name of the foreign key column that represents your association in the table model.
I use it in the following code snippet to tell Hibernate it shall use the column book_key as the foreign key column of the many-to-one association.
@Entity public class Review { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id", updatable = false, nullable = false) private Long id; private String comment; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "book_key") private Book book; }
When you activate the logging of SQL statements and fetch a Review entity from the database, you can see that Hibernate uses the book_key column to map the association.
12:48:50,686 DEBUG [org.hibernate.SQL] - select reviews0_.book_key as book_key3_2_0_, reviews0_.id as id1_2_0_, reviews0_.id as id1_2_1_, reviews0_.book_key as book_key3_2_1_, reviews0_.comment as comment2_2_1_ from Review reviews0_ where reviews0_.book_key=?
Using the @PrimaryKeyJoinColumn annotation
When you use the inheritance mapping strategy JOINED, all columns mapped by the superclass get mapped to one database table, and the specific attributes of a subclass get mapped to a different table. Hibernate has to join these 2 tables, whenever you use the subclass. The primary key columns of each table are then used as the join columns.
You can see the superclass of such an inheritance hierarchy in the following code snippet.
@Entity @Inheritance(strategy = InheritanceType.JOINED) public class Publication { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Version private int version; ... }
By default, Hibernate expects that the primary key columns of both tables have the same name. If that’s not the case, you can annotate your subclass with a @PrimaryKeyJoinColumn.
@Entity @PrimaryKeyJoinColumn(name = "book_id") public class Book extends Publication { private String title; @OneToMany(mappedBy = "book", cascade = CascadeType.REMOVE) private List<Review> reviews = new ArrayList<Review>(); ... }
As you can see in the log message, Hibernate maps the primary key of the book table to the book_id column.
12:48:50,681 DEBUG [org.hibernate.SQL] - select book0_.book_id as id1_1_0_, book0_1_.version as version2_1_0_, book0_.title as title1_0_0_ from Book book0_ inner join Publication book0_1_ on book0_.book_id=book0_1_.id where book0_.book_id=?
Learn more:
If you want to learn more about foreign key mappings, you should read the following articles:
- Ultimate Guide – Association Mappings with JPA and Hibernate
- Hibernate Tips: How to map an entity to multiple tables
Hibernate Tips Book
Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.
It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.