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

25 min

Lesson 11 of 17

1d streak

The 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.

StrategyTable StructureQuery PerformanceData Normalization
SINGLE_TABLE (Default)One table for entire hierarchy with discriminator columnFastest (zero joins, simple SELECTs)Denormalized (subclass columns must be nullable)
JOINEDOne table for base class, separate tables for each subclassModerate (requires INNER/LEFT JOIN across tables)Fully normalized (NOT NULL constraints enforced)
TABLE_PER_CLASSIndependent tables for each concrete subclassPoor 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:

PaymentEntity.java
@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

  1. Break: Add NOT NULL seatCount to Car under SINGLE_TABLE
  2. Observe: Truck inserts fail because the shared table demands a value for every subtype column
  3. 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

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