Foundation · Build
Entity Inheritance Strategies
@Inheritance maps Java hierarchies to tables three ways; each trades normalization against query cost, and switching later is a migration.
Primary source: Hibernate 6.6: Inheritance Strategies
Lesson 11 of 17
1d streakThe Architectural Question
SINGLE_TABLE forces every subtype column nullable, JOINED joins on every read, TABLE_PER_CLASS cripples polymorphic queries—none is free, and the wrong default haunts the schema for years.
What this guide proves
- Compare SINGLE_TABLE, JOINED, and TABLE_PER_CLASS honestly
- Use discriminator columns to tell subtypes apart
- Pick per hierarchy from measured queries, not habit
The three JPA inheritance strategies
Relational databases do not support object-oriented class inheritance natively. JPA provides three distinct mapping strategies with radically different query performance and normalization profiles.
| Strategy | Table Structure | Query Performance | Data Normalization |
|---|---|---|---|
| SINGLE_TABLE (Default) | One table for entire hierarchy with discriminator column | Fastest (zero joins, simple SELECTs) | Denormalized (subclass columns must be nullable) |
| JOINED | One table for base class, separate tables for each subclass | Moderate (requires INNER/LEFT JOIN across tables) | Fully normalized (NOT NULL constraints enforced) |
| TABLE_PER_CLASS | Independent tables for each concrete subclass | Poor on polymorphic queries (requires SQL UNION) | Separate tables with duplicate column definitions |
Active Recall Checkpoint
Why is SINGLE_TABLE the most popular strategy despite having nullable columns?
Hint: Think about database query joins and performance.
Show answer & explanation
It requires zero SQL JOINs or UNIONs when querying polymorphic entities, providing unmatched read and write performance.
Configuring discriminator columns for single-table inheritance
Under SINGLE_TABLE inheritance, JPA uses a discriminator column to record the concrete subtype of each database row. Here is the canonical configuration:
@Entity
@Table(name = "payments")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "payment_type", discriminatorType = DiscriminatorType.STRING)
public abstract class PaymentEntity {
@Id @GeneratedValue private UUID id;
private double amount;
}
@Entity
@DiscriminatorValue("CREDIT_CARD")
public class CreditCardPayment extends PaymentEntity {
private String cardLastFour;
}Choosing an inheritance model
Use it when
Use SINGLE_TABLE when subclass differences are small and query speed is paramount.
Reconsider when
Use JOINED when subclasses have many distinct non-nullable columns and relational integrity is strictly mandated.
Synthesis & Production Verification
Deliberate Failure Condition
- Break: Add NOT NULL seatCount to Car under SINGLE_TABLE
- Observe: Truck inserts fail because the shared table demands a value for every subtype column
- Repair: Shared-table strategies cannot enforce subtype-specific constraints; JOINED keeps NOT NULL possible at the cost of joins.
Production Acceptance Criteria
- Generate DDL for each strategy and read the differences
- Execute one polymorphic query and compare its SQL
- State which strategy fits sparse vs dense subtype fields
Key Takeaway
SINGLE_TABLE delivers the fastest polymorphic queries with nullable columns; JOINED normalizes tables at the cost of join overhead.
Architectural & Technical Review
Core Interview Questions
Q01What are the performance advantages of SINGLE_TABLE inheritance?Show answer
It requires zero joins or unions to query polymorphic hierarchies, making reads and writes extremely fast.
Q02What is the drawback of SINGLE_TABLE inheritance?Show answer
All subclass columns must be nullable in the database schema, weakening database-level constraint enforcement.
Q03When is JOINED inheritance preferred over SINGLE_TABLE?Show answer
When subclasses have many distinct non-nullable attributes and strict relational integrity is required.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Using TABLE_PER_CLASS with polymorphic queries — Polymorphic queries across TABLE_PER_CLASS generate expensive SQL UNION queries that scale poorly with data volume.
- Pitfall: Creating deeply nested inheritance hierarchies in persistence entities — Inheritance hierarchies beyond two levels create confusing schemas and complicate query optimization.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources