4. Inheritance Mappings
1. @Inheritance
About
@Inheritance
is an annotation used in JPA to define inheritance mapping strategies between entity classes.It specifies how the inheritance between parent and child entity classes should be mapped into relational database tables.
Why Is It Needed?
In Java, it's natural to use class inheritance for code reuse and modeling hierarchy.
In relational databases, there is no native inheritance — every table is flat.
So JPA must simulate inheritance by deciding how to map the class hierarchy to tables.
Where @Inheritance
is Used ?
@Inheritance
is Used ?When we have:
A base entity class (abstract or concrete).
Multiple subclasses extending the base.
We want the inheritance relationship persisted properly in DB.
Syntax of @Inheritance
strategy
is mandatory. It tells JPA which way to map the hierarchy.
Inheritance Strategies in JPA
There are 3 official strategies under @Inheritance(strategy = ...)
:
SINGLE_TABLE
One table for all classes.
TABLE_PER_CLASS
One table per concrete class.
JOINED
Multiple tables linked by primary keys.
1. InheritanceType.SINGLE_TABLE
All entities in the hierarchy are mapped into a single table.
One big table with columns from parent and child classes.
Discriminator column is used to differentiate which row belongs to which class.
Database Table
1
John
HR
NULL
manager
2
Jane
NULL
Java
developer
Characteristics
Performance
Fastest (only one table to join).
Schema
Sparse columns (many NULLs if many subclasses).
Flexibility
Hard to add constraints because unrelated fields exist in same table.
Discriminator
Mandatory (@DiscriminatorColumn
).
Example use case
Small inheritance hierarchies with few fields.
2. InheritanceType.TABLE_PER_CLASS
Each concrete entity gets its own table.
Each table duplicates the columns inherited from parent.
No need for discriminator column.
Database Tables
Separate table for each subclass. Each table will have own copy of inherited fields.
Manager Table
1
John
HR
3
Bob
Finance
Developer Table
2
Jane
Java
Notes:
No NULLs.
Duplicate columns (
id
,name
) in all tables.Querying across all employees needs a UNION.
Characteristics
Performance
Inserts fast. Queries across hierarchy are slow (UNION needed).
Schema
No NULL fields.
Flexibility
Good if subclasses are quite different.
Discriminator
Not needed.
Example use case
When subclasses are very different and rarely queried together.
3. InheritanceType.JOINED
Parent and child classes have their own tables.
Tables are linked via primary key / foreign key.
Fetching a subclass involves a JOIN.
Database Tables
One table for base class and one for each subclass. Tables are linked by primary key = foreign key.
Employee Table (base table)
1
John
2
Jane
3
Bob
Manager Table
1
HR
3
Finance
Developer Table
2
Java
Notes:
id
is Primary Key and Foreign Key in child tables.Fetching a full Manager/Developer record requires JOIN on
id
.Very normalized.
Characteristics
Performance
Slower (needs JOINs on select).
Schema
Normalized (no NULLs).
Flexibility
Best for strict relational modeling.
Discriminator
Optional (can use).
Example use case
When normalized design is required, and JOIN cost is acceptable.
2. @DiscriminatorColumn
About
@DiscriminatorColumn
is a JPA annotation used in the context of inheritance mapping in JPA to define a discriminator column. It helps in distinguishing between different entities in the same table when the SINGLE_TABLE
or JOINED
inheritance strategy is used. This column holds the value that determines which subclass the current row corresponds to.
Why is it Needed?
Inheritance Mapping: When using single-table inheritance, all subclasses are stored in the same table. The discriminator column is used to store the type of entity (i.e., the subclass) for each row.
Class Differentiation: In databases, there's no direct concept of inheritance, so JPA uses the discriminator column to mark which entity a row belongs to.
Performance: The discriminator column avoids using complex joins and makes querying easier and more efficient in the
SINGLE_TABLE
strategy.
Where is @DiscriminatorColumn
Used ?
@DiscriminatorColumn
Used ?It is used in the parent entity class where inheritance is being mapped.
It works in the context of
SINGLE_TABLE
orJOINED
inheritance strategies, where a single table stores all the child entity data (forSINGLE_TABLE
) or child entities have their own table but still rely on the base entity table (forJOINED
).
Syntax
name: Specifies the name of the discriminator column (e.g.,
employee_type
in the example).discriminatorType: Specifies the type of the discriminator column (
STRING
,INTEGER
,CHAR
, etc.). Default isDiscriminatorType.STRING
.
How It Works ?
The
@DiscriminatorColumn
defines a special column in the table that stores a discriminator value.The value in this column helps JPA determine which class the row belongs to.
@DiscriminatorValue
on each subclass specifies the value that will be inserted in the discriminator column for that subclass.
Example Scenario with SINGLE_TABLE
Inheritance:
SINGLE_TABLE
Inheritance:Database Table Structure (for SINGLE_TABLE
strategy):
SINGLE_TABLE
strategy):1
John
MANAGER
HR
NULL
2
Alice
DEVELOPER
NULL
Java
3
Bob
DEVELOPER
NULL
Python
Key Characteristics
Purpose
To distinguish between entities when mapped into a single table (or joined strategy).
Discriminator Value
The value in this column helps identify which subclass the row belongs to.
Column Type
Can be STRING
, CHAR
, INTEGER
, etc., depending on the data.
Use Case
Essential for the SINGLE_TABLE
inheritance strategy.
Defaults
If not defined, defaults to DTYPE
as the column name, and DiscriminatorType.STRING
for type.
Inheritance Type
Primarily used in SINGLE_TABLE
inheritance, but can also be used in JOINED
.
Customizing @DiscriminatorColumn
@DiscriminatorColumn
We can further customize the discriminator column with additional attributes:
Attributes
name: Name of the discriminator column.
discriminatorType: Type of the discriminator value (can be
STRING
,INTEGER
, etc.).length: Optional. Specifies the maximum length for the discriminator column (default is 31).
columnDefinition: Optional. Allows for specifying the column's SQL definition.
When Not to Use @DiscriminatorColumn
@DiscriminatorColumn
Performance Concerns: The
SINGLE_TABLE
strategy may become inefficient when there are a lot of fields that are not relevant for certain subclasses, leading to sparse tables with manyNULL
values. In such cases, other strategies likeJOINED
orTABLE_PER_CLASS
may be more efficient.Complex Inheritance: If the hierarchy has many deep or unrelated subclasses, managing the
@DiscriminatorColumn
can become difficult, and you might prefer using a different inheritance strategy.
Best Practices
Keep it Simple
Use SINGLE_TABLE
and @DiscriminatorColumn
for simple hierarchies. Avoid deep inheritance trees.
Column Type
Use DiscriminatorType.STRING
for most cases, but if you need a number, use DiscriminatorType.INTEGER
or CHAR
for efficiency.
Avoid NULLs
If you are using SINGLE_TABLE
strategy, consider the schema design and avoid having many NULL
columns for subclasses that don't need them.
Customization
Customize the column definition using columnDefinition
if you need more control over how the column is created in the database.
Clear Naming
Ensure clear and meaningful values for the discriminator column values using @DiscriminatorValue
.
3. @DiscriminatorValue
About
@DiscriminatorValue
is a JPA annotation used to specify the value that will be stored in the discriminator column for each subclass of a parent entity when inheritance is mapped using SINGLE_TABLE
or JOINED
inheritance strategies. The discriminator column (defined by @DiscriminatorColumn
) helps JPA differentiate between different subclasses of the same parent entity in the database.
Why is @DiscriminatorValue
Needed?
@DiscriminatorValue
Needed?Inheritance Strategy: It is crucial for the
SINGLE_TABLE
inheritance strategy where all subclasses are stored in the same table. Each subclass needs a discriminator value to tell which entity type the row corresponds to.Entity Type Identification: Without
@DiscriminatorValue
, JPA cannot distinguish between different types of entities stored in the same table.Efficient Data Storage: Helps in storing and querying different entity types in the same table, which can improve performance and reduce the need for multiple database tables in certain situations.
Where is @DiscriminatorValue
Used?
@DiscriminatorValue
Used?It is applied on subclass entities that inherit from a parent entity using a single table inheritance strategy (
SINGLE_TABLE
orJOINED
).Each subclass must declare a value for
@DiscriminatorValue
that is inserted into the discriminator column when an instance of the subclass is persisted.
Syntax of @DiscriminatorValue
@DiscriminatorValue
@DiscriminatorValue("SUBCLASS_NAME"): Specifies the value that will be stored in the discriminator column for this subclass.
How It Works ?
The
@DiscriminatorValue
annotation is applied to subclasses in the inheritance hierarchy.When an instance of the subclass is saved to the database, JPA inserts the corresponding discriminator value into the discriminator column (defined by
@DiscriminatorColumn
in the parent entity).JPA uses the value stored in the discriminator column to identify which subclass the row belongs to when querying the data.
Example
Consider a scenario where we have an Employee
superclass and two subclasses: Manager
and Developer
.
Parent Entity
Subclass 1: Manager
Subclass 2: Developer
Database Table Structure (for SINGLE_TABLE
strategy)
1
John
MANAGER
HR
NULL
2
Alice
DEVELOPER
NULL
Java
3
Bob
DEVELOPER
NULL
Python
In this case:
The
employee_type
column is the discriminator column.The value
"MANAGER"
is inserted for theManager
subclass, and"DEVELOPER"
for theDeveloper
subclass.
Characteristics of @DiscriminatorValue
@DiscriminatorValue
Purpose
Specifies the value that will be stored in the discriminator column for a specific subclass.
Target
Applied to subclasses in an inheritance hierarchy.
Inheritance Strategy
Primarily used in the SINGLE_TABLE
inheritance strategy. It can also be used in JOINED
.
Discriminator Column
The value is inserted into the column defined by @DiscriminatorColumn
.
Value Type
The value can be a string, integer, or other simple types, based on the discriminator column type.
Role
Helps JPA identify which subclass the row in the table represents.
Required
Yes, each subclass in a SINGLE_TABLE
inheritance strategy must declare a discriminator value.
Default Behavior of @DiscriminatorValue
@DiscriminatorValue
If @DiscriminatorValue
is not specified on a subclass, JPA will use the class name (converted to a string) as the discriminator value by default.
Example (Implicit Default):
If @DiscriminatorValue
were omitted, the discriminator value for Manager
would be automatically set to "Manager"
, which is the name of the class.
Customizing @DiscriminatorValue
@DiscriminatorValue
We can customize the discriminator values to make them more readable and relevant to the domain model.
In this case, the value "HR_MANAGER"
will be used for rows representing HRManager
in the discriminator column.
When Not to Use @DiscriminatorValue
@DiscriminatorValue
Complex Relationships: When the inheritance hierarchy involves complex relationships, consider using the
JOINED
strategy instead, which splits each class into its own table.Multiple Inheritance: If the entity hierarchy is deep with many unrelated subclasses, the
SINGLE_TABLE
strategy might become inefficient because of the large number ofNULL
values in the columns.
Last updated
Was this helpful?