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:
SINGLE_TABLE
JOINED
TABLE_PER_CLASS
.
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
The strategy 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
strategyThe strategy 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
The JOINED
strategy normalizes the database tables, meaning each class has its own table including the columns for the fields declared in that class.

JOINED
strategyThe 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
With the 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
strategyThe 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.