Associations with JPA and Hibernate
The handling of associations between entities and their underlying database records is one of the key strengths of JPA. It hides most of the technical complexity and enables you to concentrate on the business logic you want to implement.
At the same time, it’s often the reason for performance problems. A seemingly small misconfiguration in your mapping definition or a missing optimization when loading your entities can cause lots of unexpected SQL statements.
You can easily avoid these issues, if you have a solid understanding of the mapping definitions, know when and why Hibernate executes additional queries and follow a few best practices.
Association Mappings
The definition of a basic entity mapping is simple. It only requires an entity attribute and 1-2 annotations. On the right, you can see an example mapping of a standard many-to-one association mapping.
Based on this mapping, your persistence provider, e.g., Hibernate, knows the database tables and the foreign columns that represent the association in your table model. It then generates all the required SQL statements to fetch the association from the database and to persist all changes.
I explain all of these mappings in great detail in the following article. If you don’t have a lot of experience with the mapping of associations, you should start there.
Advanced Association Mappings
OK, let’s take it one step further. Based on the basic mappings described in the previous article, you can model all kinds of associations. You can model self-referencing associations, persist additional attributes for each association record, define associations between more than 2 entities and much more.
Mapping Collections with Hibernate and JPA
Modeling self-referencing associations with Hibernate
Ternary Associations – Modelling Associations between 3 Entities
Improve Usability and Avoid Performance Issues
If you want to use these different kinds of associations as efficient as possible, you also need to be familiar with JPA’s FetchTypes, the side-effects of cascade operations, and Hibernate’s handling of different Collection types.
FetchType: Lazy/Eager loading for Hibernate & JPA
How to Choose the Most Efficient Data Type for To-Many Associations – Bag vs. List vs. Set
Why you should avoid CascadeType.REMOVE for to-many associations and what to do instead
Association Fetching
The way you fetch your associations often makes the difference between a blazingly fast application and huge performance problems. But don’t worry, doing it right is much easier as you might think. As long as you use the FetchType.LAZY and initialize all required associations when you fetch your entity, you should avoid at least 90% of all performance problems.
FetchType: Lazy/Eager loading for Hibernate & JPA
How to Initialize Entity Associations with Spring Data JPA
Your 2 best options to fix Hibernate’s MultipleBagFetchException
Best Practices
The easiest way to ensure that you applied the most important parts of all the things you learned in the previously mentioned articles is to follow common best practices. So, make sure to keep the following articles at hand and to check them regularly.