|

Hibernate Tips: Map an Unidirectional One-to-Many Association Without a Junction Table


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 leave a comment below.

Question:

My table model contains a normal one-to-many association using a foreign key column on the table that represents the to-many side. When I map this association as a unidirectional one-to-many association with Hibernate, it uses a junction table instead of the foreign key column. How can I fix that?

Solution:

As I explained in great details in my article about best practices for one-to-many association mappings, Hibernate handles unidirectional one-to-many mappings very inefficiently. You should, therefore, try to avoid them and use a bidirectional one-to-many/many-to-one mapping instead.

If there are any reasons that prevent you from using a bidirectional relationship, you can specify the foreign key column with a @JoinColumn annotation. But please be aware that this only prevents Hibernate from using the junction or association table. As you will see in the following example, the mapping is still not as efficient as a bidirectional one.

Add @JoinColumn to avoid a junction table

Here you can see an example of a PurchaseOrder entity that models a unidirectional one-to-many relationship to the Item entity. I added the @JoinColumn annotation to tell Hibernate that it shall use the fk_order column of the Item table to map the association.

@Entity
public class PurchaseOrder {
	
	@OneToMany
	@JoinColumn(name = "fk_order")
	private Set<Item> items = new HashSet<Item>();

	...
}

Inefficient association management

When you now persist a new Item entity and add it to the association, you can see that Hibernate no longer uses a junction table to persist the relationship.

15:31:15,788 DEBUG SQL:92 - 
    insert 
    into
        Item
        (name, version, id) 
    values
        (?, ?, ?)
15:31:15,790 DEBUG SQL:92 - 
    update
        PurchaseOrder 
    set
        version=? 
    where
        id=? 
        and version=?
15:31:15,793 DEBUG SQL:92 - 
    update
        Item 
    set
        fk_order=? 
    where
        id=?

But you can also see that Hibernate executes 2 unnecessary SQL UPDATE statements. Hibernate first persists the Item entity without setting the foreign key reference to the PurchasOrder entity. It then updates the PurchaseOrder before it updates the new Item to set the foreign key reference.

The only way to avoid these UPDATE statements is to use a bidirectional or a unidirectional many-to-one mapping. Hibernate then sets the foreign key reference in the INSERT statement without executing any additional SQL statements.

Learn more:

If you want to learn more about JPA’s and Hibernate’s association mapping capabilities, you will enjoy the following articles:

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.

Get it now!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.