Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Inheritance Mapping

Inheritance is a fundamental concept in object-oriented programming that allows one class to inherit properties and behaviors from another class. In relational databases, there isn't a direct way to represent inheritance. Hibernate provides strategies to map an inheritance hierarchy into relational databases. Here are the main inheritance mapping strategies in Hibernate:

1. Table Per Hierarchy (Single Table Strategy)

  • A single table is used to map the whole class hierarchy.
  • A discriminator column is used to differentiate between entity types.

Pros:

  • Requires only one table, which can be more efficient for read operations.

Cons:

  • The table can have many nullable columns if subclasses have properties that don't apply to other subclasses.

Example:

For an inheritance hierarchy of Vehicle, Car, and Bike, you'd have one table named VEHICLE with columns specific to both Car and Bike and a discriminator column to differentiate between records of type Car and Bike.

2. Table Per Concrete Class (Concrete Table Strategy)

  • One table for each concrete class in the hierarchy.
  • Tables for subclasses will have columns for inherited attributes.

Pros:

  • Normalized schema with no nullable columns.

Cons:

  • May require UNION queries to fetch data across the hierarchy, making retrieval operations less efficient.

Example:

For the Vehicle, Car, and Bike hierarchy, there would be two tables: CAR and BIKE. Both tables will have columns for attributes defined in the Vehicle class.

3. Table Per Subclass (Joined Subclass Strategy)

  • One table for the superclass and one table for each subclass.
  • Subclass tables only contain columns for additional properties and share the primary key with the superclass table.

Pros:

  • More normalized than the single table strategy.
  • Doesn't require UNION queries like the concrete table strategy.

Cons:

  • Requires JOIN operations to retrieve properties across the hierarchy.

Example:

For the Vehicle, Car, and Bike hierarchy, there would be three tables: VEHICLE, CAR, and BIKE. The CAR and BIKE tables would have foreign keys that reference the primary key of the VEHICLE table.

Usage in Hibernate:

Here's how you'd represent inheritance mapping using annotations:

  • Table Per Hierarchy:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "vehicle_type")
public class Vehicle { /* common attributes */ }

@Entity
@DiscriminatorValue("car")
public class Car extends Vehicle { /* car-specific attributes */ }

@Entity
@DiscriminatorValue("bike")
public class Bike extends Vehicle { /* bike-specific attributes */ }
  • Table Per Concrete Class:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle { /* common attributes */ }

@Entity
public class Car extends Vehicle { /* car-specific attributes */ }

@Entity
public class Bike extends Vehicle { /* bike-specific attributes */ }
  • Table Per Subclass:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Vehicle { /* common attributes */ }

@Entity
@PrimaryKeyJoinColumn(name = "vehicle_id")
public class Car extends Vehicle { /* car-specific attributes */ }

@Entity
@PrimaryKeyJoinColumn(name = "vehicle_id")
public class Bike extends Vehicle { /* bike-specific attributes */ }

In conclusion, the choice of inheritance mapping strategy depends on your application's specific requirements and the trade-offs you're willing to accept between normalization and performance.

  1. Implementing single table inheritance in Hibernate:

    • Description: In Single Table inheritance, all classes in the hierarchy are mapped to a single database table. A discriminator column is used to distinguish between different types of entities.
    • Code:
      @Entity
      @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
      @DiscriminatorColumn(name = "employee_type", discriminatorType = DiscriminatorType.STRING)
      public abstract class Employee {
          // Common fields and methods
      }
      
      @Entity
      @DiscriminatorValue("FT")
      public class FullTimeEmployee extends Employee {
          // Fields and methods specific to FullTimeEmployee
      }
      
      @Entity
      @DiscriminatorValue("PT")
      public class PartTimeEmployee extends Employee {
          // Fields and methods specific to PartTimeEmployee
      }
      
  2. Table per concrete class mapping in Hibernate:

    • Description: In Table per Concrete Class strategy, each concrete class in the hierarchy is mapped to a separate table. No common table for the hierarchy is created.
    • Code:
      @Entity
      @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
      public abstract class Employee {
          // Common fields and methods
      }
      
      @Entity
      public class FullTimeEmployee extends Employee {
          // Fields and methods specific to FullTimeEmployee
      }
      
      @Entity
      public class PartTimeEmployee extends Employee {
          // Fields and methods specific to PartTimeEmployee
      }
      
  3. Mapping joined table inheritance in Hibernate:

    • Description: In Joined Table inheritance, each class in the hierarchy is mapped to a separate table. Common fields are stored in the base table, and subclass tables contain only the fields specific to that subclass.
    • Code:
      @Entity
      @Inheritance(strategy = InheritanceType.JOINED)
      public abstract class Employee {
          @Id
          @GeneratedValue(strategy = GenerationType.IDENTITY)
          private Long id;
      
          // Common fields and methods
      }
      
      @Entity
      public class FullTimeEmployee extends Employee {
          private double salary;
      
          // Fields and methods specific to FullTimeEmployee
      }
      
      @Entity
      public class PartTimeEmployee extends Employee {
          private double hourlyRate;
      
          // Fields and methods specific to PartTimeEmployee
      }