# 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 ?

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

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Parent {
    // fields
}
```

* `strategy` is mandatory. It tells JPA **which way** to map the hierarchy.

### Inheritance Strategies in JPA

There are **3 official strategies** under `@Inheritance(strategy = ...)`:

<table><thead><tr><th width="311.125">Strategy</th><th>Meaning</th></tr></thead><tbody><tr><td><code>SINGLE_TABLE</code></td><td>One table for all classes.</td></tr><tr><td><code>TABLE_PER_CLASS</code></td><td>One table per concrete class.</td></tr><tr><td><code>JOINED</code></td><td>Multiple tables linked by primary keys.</td></tr></tbody></table>

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

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

```java
@Entity
@DiscriminatorValue("manager")
public class Manager extends Employee {
    private String departmentName;
}
```

```java
@Entity
@DiscriminatorValue("developer")
public class Developer extends Employee {
    private String programmingLanguage;
}
```

#### Database Table

<table><thead><tr><th width="75.4453125">id</th><th width="88.7421875">name</th><th width="170.921875">departmentName</th><th>programmingLanguage</th><th>type</th></tr></thead><tbody><tr><td>1</td><td>John</td><td>HR</td><td>NULL</td><td>manager</td></tr><tr><td>2</td><td>Jane</td><td>NULL</td><td>Java</td><td>developer</td></tr></tbody></table>

#### Characteristics

<table><thead><tr><th width="166.21484375">Aspect</th><th>Details</th></tr></thead><tbody><tr><td>Performance</td><td>Fastest (only one table to join).</td></tr><tr><td>Schema</td><td>Sparse columns (many NULLs if many subclasses).</td></tr><tr><td>Flexibility</td><td>Hard to add constraints because unrelated fields exist in same table.</td></tr><tr><td>Discriminator</td><td>Mandatory (<code>@DiscriminatorColumn</code>).</td></tr><tr><td>Example use case</td><td>Small inheritance hierarchies with few fields.</td></tr></tbody></table>

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

```java
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Employee {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
}
```

```java
@Entity
public class Manager extends Employee {
    private String departmentName;
}
```

```java
@Entity
public class Developer extends Employee {
    private String programmingLanguage;
}
```

#### Database Tables

Separate table for each subclass.\
Each table will have own copy of inherited fields.

Manager Table

| id | name | departmentName |
| -- | ---- | -------------- |
| 1  | John | HR             |
| 3  | Bob  | Finance        |

Developer Table

| id | name | programmingLanguage |
| -- | ---- | ------------------- |
| 2  | Jane | Java                |

**Notes**:

* No NULLs.
* Duplicate columns (`id`, `name`) in all tables.
* Querying across all employees needs a **UNION**.

#### Characteristics

<table><thead><tr><th width="171.01171875">Aspect</th><th>Details</th></tr></thead><tbody><tr><td>Performance</td><td>Inserts fast. Queries across hierarchy are slow (UNION needed).</td></tr><tr><td>Schema</td><td>No NULL fields.</td></tr><tr><td>Flexibility</td><td>Good if subclasses are quite different.</td></tr><tr><td>Discriminator</td><td>Not needed.</td></tr><tr><td>Example use case</td><td>When subclasses are very different and rarely queried together.</td></tr></tbody></table>

### 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**.

```java
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

```java
@Entity
public class Manager extends Employee {
    private String departmentName;
}
```

```java
@Entity
public class Developer extends Employee {
    private String programmingLanguage;
}
```

#### Database Tables

One table for base class and one for each subclass.\
Tables are linked by primary key = foreign key.

Employee Table (base table)

| id | name |
| -- | ---- |
| 1  | John |
| 2  | Jane |
| 3  | Bob  |

Manager Table

| id | departmentName |
| -- | -------------- |
| 1  | HR             |
| 3  | Finance        |

Developer Table

| id | programmingLanguage |
| -- | ------------------- |
| 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

<table><thead><tr><th width="218.45703125">Aspect</th><th>Details</th></tr></thead><tbody><tr><td>Performance</td><td>Slower (needs JOINs on select).</td></tr><tr><td>Schema</td><td>Normalized (no NULLs).</td></tr><tr><td>Flexibility</td><td>Best for strict relational modeling.</td></tr><tr><td>Discriminator</td><td>Optional (can use).</td></tr><tr><td>Example use case</td><td>When normalized design is required, and JOIN cost is acceptable.</td></tr></tbody></table>

## 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 ?

* It is used in the **parent entity class** where inheritance is being mapped.
* It works in the context of `SINGLE_TABLE` or `JOINED` inheritance strategies, where a single table stores all the child entity data (for `SINGLE_TABLE`) or child entities have their own table but still rely on the base entity table (for `JOINED`).

### Syntax

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING)
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

* **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 is `DiscriminatorType.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:

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING)
public class Employee {
    @Id
    private Long id;
    private String name;
}

@Entity
@DiscriminatorValue("MANAGER")
public class Manager extends Employee {
    private String departmentName;
}

@Entity
@DiscriminatorValue("DEVELOPER")
public class Developer extends Employee {
    private String programmingLanguage;
}
```

#### Database Table Structure (for `SINGLE_TABLE` strategy):

| id | name  | employee\_type | departmentName | programmingLanguage |
| -- | ----- | -------------- | -------------- | ------------------- |
| 1  | John  | MANAGER        | HR             | NULL                |
| 2  | Alice | DEVELOPER      | NULL           | Java                |
| 3  | Bob   | DEVELOPER      | NULL           | Python              |

### Key Characteristics

<table data-full-width="true"><thead><tr><th width="190.51953125">Feature</th><th>Details</th></tr></thead><tbody><tr><td><strong>Purpose</strong></td><td>To distinguish between entities when mapped into a single table (or joined strategy).</td></tr><tr><td><strong>Discriminator Value</strong></td><td>The value in this column helps identify which subclass the row belongs to.</td></tr><tr><td><strong>Column Type</strong></td><td>Can be <code>STRING</code>, <code>CHAR</code>, <code>INTEGER</code>, etc., depending on the data.</td></tr><tr><td><strong>Use Case</strong></td><td>Essential for the <code>SINGLE_TABLE</code> inheritance strategy.</td></tr><tr><td><strong>Defaults</strong></td><td>If not defined, defaults to <code>DTYPE</code> as the column name, and <code>DiscriminatorType.STRING</code> for type.</td></tr><tr><td><strong>Inheritance Type</strong></td><td>Primarily used in <code>SINGLE_TABLE</code> inheritance, but can also be used in <code>JOINED</code>.</td></tr></tbody></table>

### Customizing `@DiscriminatorColumn`

We can further customize the **discriminator column** with additional attributes:

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name = "employee_type",
    discriminatorType = DiscriminatorType.STRING,
    length = 50, // Set the maximum length of the discriminator value
    columnDefinition = "VARCHAR(50) NOT NULL" // Custom SQL definition for the column
)
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

#### 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`

* **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 many `NULL` values. In such cases, other strategies like `JOINED` or `TABLE_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

<table data-full-width="true"><thead><tr><th width="147.17578125">Best Practice</th><th>Details</th></tr></thead><tbody><tr><td><strong>Keep it Simple</strong></td><td>Use <code>SINGLE_TABLE</code> and <code>@DiscriminatorColumn</code> for simple hierarchies. Avoid deep inheritance trees.</td></tr><tr><td><strong>Column Type</strong></td><td>Use <code>DiscriminatorType.STRING</code> for most cases, but if you need a number, use <code>DiscriminatorType.INTEGER</code> or <code>CHAR</code> for efficiency.</td></tr><tr><td><strong>Avoid NULLs</strong></td><td>If you are using <code>SINGLE_TABLE</code> strategy, consider the schema design and avoid having many <code>NULL</code> columns for subclasses that don't need them.</td></tr><tr><td><strong>Customization</strong></td><td>Customize the column definition using <code>columnDefinition</code> if you need more control over how the column is created in the database.</td></tr><tr><td><strong>Clear Naming</strong></td><td>Ensure clear and meaningful values for the discriminator column values using <code>@DiscriminatorValue</code>.</td></tr></tbody></table>

## 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?

* **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?

* It is applied on **subclass entities** that inherit from a parent entity using a **single table inheritance strategy** (`SINGLE_TABLE` or `JOINED`).
* 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`

```java
@Entity
@DiscriminatorValue("SUBCLASS_NAME")
public class Subclass extends ParentClass {
    // Class implementation
}
```

* **@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**

```java
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING)
public class Employee {
    @Id
    private Long id;
    private String name;
    // Getter and Setter methods
}
```

**Subclass 1:** `Manager`

```java
@Entity
@DiscriminatorValue("MANAGER")
public class Manager extends Employee {
    private String departmentName;
    // Getter and Setter methods
}
```

**Subclass 2:** `Developer`

```java
@Entity
@DiscriminatorValue("DEVELOPER")
public class Developer extends Employee {
    private String programmingLanguage;
    // Getter and Setter methods
}
```

**Database Table Structure** (for `SINGLE_TABLE` strategy)

| id | name  | employee\_type | departmentName | programmingLanguage |
| -- | ----- | -------------- | -------------- | ------------------- |
| 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 the `Manager` subclass, and `"DEVELOPER"` for the `Developer` subclass.

### Characteristics of `@DiscriminatorValue`

<table data-full-width="true"><thead><tr><th width="198.67578125">Feature</th><th>Details</th></tr></thead><tbody><tr><td><strong>Purpose</strong></td><td>Specifies the value that will be stored in the discriminator column for a specific subclass.</td></tr><tr><td><strong>Target</strong></td><td>Applied to subclasses in an inheritance hierarchy.</td></tr><tr><td><strong>Inheritance Strategy</strong></td><td>Primarily used in the <code>SINGLE_TABLE</code> inheritance strategy. It can also be used in <code>JOINED</code>.</td></tr><tr><td><strong>Discriminator Column</strong></td><td>The value is inserted into the column defined by <code>@DiscriminatorColumn</code>.</td></tr><tr><td><strong>Value Type</strong></td><td>The value can be a string, integer, or other simple types, based on the discriminator column type.</td></tr><tr><td><strong>Role</strong></td><td>Helps JPA identify which subclass the row in the table represents.</td></tr><tr><td><strong>Required</strong></td><td>Yes, each subclass in a <code>SINGLE_TABLE</code> inheritance strategy must declare a discriminator value.</td></tr></tbody></table>

### Default Behavior of `@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):

```java
@Entity
@DiscriminatorValue("MANAGER")
public class Manager extends Employee {
    private String departmentName;
}
```

If `@DiscriminatorValue` were omitted, the discriminator value for `Manager` would be automatically set to `"Manager"`, which is the name of the class.

### Customizing `@DiscriminatorValue`

We can customize the discriminator values to make them more readable and relevant to the domain model.

```java
@Entity
@DiscriminatorValue("HR_MANAGER")
public class HRManager extends Manager {
    private String region;
    // Getter and Setter methods
}
```

In this case, the value `"HR_MANAGER"` will be used for rows representing `HRManager` in the discriminator column.

### When Not to Use `@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 of `NULL` values in the columns.
