In this post I want to present four basic strategies for mapping class inheritance in Hibernate:
- No inheritance - just copy superclass properties to subclasses
- Table per class hierarchy
- Table per concrete class
- Table per every class
This strategy is used if we want to share Java code between entity classes.
An example will show us how it works.
Let’s say we want to avoid declaring
version fields in every entity
We can solve this by creating abstract superclass
BaseEntity that will hold common code
and annotating it with
@MappedSuperclass to enable no inheritance strategy.
BaseEntity class code:
Now we may create two independent entity classes
version fields with mappings from
For given classes Hibernate will generate database schema:
Since this strategy is used to only share Java code we should not query database
BaseEntity instances. If we do Hibernate will execute many select statements -
one for every class inheriting from
Will result in queries:
NOTE: Querying for
BaseEntity via JPA will throw exception with message
Not an entity: class BaseEntity. We
can query for
BaseEntity only via Hibernate
We will use our
BaseEntity class in the example code of the remaining strategies to show that
it can be mixed with “real” ORM inheritance.
Table per class hierarchy
In this strategy all subclasses data will be stored in single table. A special column called discriminator is added to that table to help Hibernate know which subclass is stored in given row.
An example will show how it works. We start by creating a superclass called
And two subclasses
To enable table per hierarchy strategy, superclass must be marked as
@Entity and must have
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) annotation.
We can choose discriminator column name and type using
Subclasses must be marked as
@Entity and can provide values for
discriminator column via
@DiscriminatorValue annotation (discriminator value defaults to class name).
For this example Hibernate will generate schema:
Let’s save some data:
And check how they are stored in database:
Saving was easy, now let’s check querying. We start
by getting all
Animal instances from database:
This will result in SQL query:
With this strategy we may also query specific animal types e.g. cats:
This will result in the following SQL:
We can see that Hibernate added test for discriminator column
limit returned animals to cats only.
Before we move to next strategy let’s see what are pros and cons of table per hierarchy strategy:
|Fast - no joins are needed to retrieve data|
|Simple - only single table is needed in database|
|Cannot create constrains in database - all columns representing subclass data must be nullable. This is serious drawback because without constrains data can be easily corrupted by application bug or by inattentive users|
|Wasted space - when subclasses have many fields shared table will contain many columns most of which will contain
Table per concrete class
This inheritance strategy will generate database table per each concrete class in
the hierarchy. Let’s demonstrate on example.
Given classes (abstract classes are in the blue boxes):
This strategy will generate tables for
Here is code for all classes used in this example:
To enable table per concrete class strategy, root of the inheritance hierarchy must
be marked as
@Entity and must have
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
annotation. All subclasses (even abstract ones) must be marked as
@Entity. Abstract classes
will not be represented in database.
Animal example Hibernate will generate database schema:
When we query for all instances of
Hibernate uses SQL subquery and
union all operator to gather rows from
all tables containing subclasses data. To differentiate between subclasses
in the result set, Hibernate adds special column
clazz_ that will contain different numbers
for different subclasses:
When we query for one of the concrete subclasses Hibernate will directly query table containing that subclass data. For example:
Will generate SQL query:
Before we move to the next strategy let’s consider one more example. Say
we want to store photos of animals using
For this class Hibernate will generate table:
This time I used SQL instead of table picture to show an important fact.
Do you see
animal_id column in that table, it will be used to
connect photos to animals. Unfortunately because various types of animals are
stored in different tables we cannot create foreign key constraint on
that column, this is serious drawback of table per concrete class strategy.
When we query for all photos with animals:
Hibernate will execute this monstrous query:
I only add that complicated queries like this may cause serious performance problems.
To sum up here are pros and cons of table per concrete class strategy:
|Constraint friendly - You can introduce separate database constrains for each concrete subclass|
|Fast when querying concrete subclasses (queries directly access subclass table)|
|May be slow when you query/lazy load abstract superclasses (
|Cannot introduce foreign key constrains for superclasses references (like in
As you see when you are not using references to superclasses in your model this is strategy to go. When you have many references to superclasses it is better to use single table or table per every class strategies.
Table per every class
To demonstrate table per every class strategy we’ll use the same example that was used in the description of table per concrete class strategy:
Here are Java classes annotated to use table per every class strategy:
Notice that every class is marked as
@Entity and root of inheritance hierarchy is
@Inheritance(strategy = InheritanceType.JOINED). By default
primary keys in tables corresponding to mapped classes will be named
it is useful to change name of the primary key column, we can use
@PrimaryKeyJoinColumn(name = "primary_key_name") to provide new primary key column name.
For given example Hibernate will generate database schema: Notice that Hibernate generated table per every class in the hierarchy. Lines between tables represent foreign key constrains inside database.
In table per every class strategy data from superclasses will be stored in dedicated tables, SQL joins will be used to gather entity data from all superclasses. When we add new entity to database Hibernate will split it according to inheritance hierarchy and will execute many inserts. An example will help us understand how it works.
First let’s try to insert some grumpy animals into database:
To save single
GrumpyCat entity to database Hibernate must generate three inserts:
Let’s see what will happen when we try to load all
GrupyCats from database:
Hibernate will execute following SQL query:
As we can see Hibernate used
inner joins to gather
that was split into
If we would query for
Animals there would be ever more
Now let’s see how storing/retrieving animal photos changed in table
per every class strategy. We will use the same
Photo class as in previous example:
First we must notice that
Photo table now has a foreign key constrain to
When we try to query database for all photos with animals:
Hibernate will execute query:
This is really heavy query if plenty of
joins, it may cause some performance problems.
Let’s end by presenting pros and cons of table per every class strategy:
|Constraint friendly - we may easily add constrains to database. References to superclasses are guarded by foreign key constrains.|
|Poor performance - simple operations like saving entity to database or reading entity from database often require many SQL statements or complicated SQL queries with joins|
Before using this strategy you should consider using simpler and faster table per hierarchy strategy. Use this strategy only if you have many subclasses that define many fields that cannot by shared using superclass.
That was really long post, I hope it help you understand various inheritance strategies that we can use in Hibernate. As always with ORM’s the key to master this material is to spend few hours creating dummy models with mappings and checking what queries Hibernate generate.