This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe possible performance impacts of JPA inheritance mapping strategies.
JPA supports three inheritance mapping strategies:
This blog post describes the databases tables for the three inheritance mapping strategies using the following class model with two superclasses Person and Employee and three subclasses FullTimeEmployee, PartTimeEmployee and ExternalEmployee.
SINGLE_TABLE stores all instances of an inheritance hierarchy in a single table. Fields not part of the concrete class are left empty.
SINGLE_TABLE is the default, if there is no strategy specified. In most cases the strategy
SINGLE_TABLE has in the best performance. There is a small drawback: columns for attributes declared in sibling other classes of the hierarchy include
NULL values. So these columns need to be nullable although they might not be null in the object model.
JOINED strategy normalizes the database tables, meaning each class has its own table including the columns for the fields declared in that class.
JOINED strategy results in many join operations when loading instances. In the above example there are separate tables for Person, Employee and the three Employee subclasses. So the
SELECT statement loading a FullTimeEmployee instance need to join the Person, the Employee and the FullTimeEmployee table.
This strategy should be used when most of the instances are of type Person or Employee. Then the instances occupy less space in the database compared to
SINGLE_TABLE, because no
NULL values are stored for attributes of other classes in the hierarchy.
TABLE_PER_CLASS strategy each concrete subclass gets its own table with columns for all the fields of the class including the inherited fields.
TABLE_PER_CLASS strategie may result in poor performance when using JPQL queries over the superclass Person, because it might result in
UNION SQL queries. The same holds true for navigating a relationship to the superclass of an inheritance with
TABLE_PER_CLASS strategy. The related instance is stored in one of several tables.
This strategie should be used if the superclasses Person and Employee are abstract and if the application does not treat the instances of the concrete subclasses as Person or Employee.
Recommendation: Try the
SINGLE_TABLE inheritance strategy first.
You can find an example of this pitfall and its solution in the classes JoinedInheritanceStrategyExperiment and TablePerClassInheritanceStrategyExperiment in this project: https://github.com/akquinet/jpapitfalls.git.