Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Table Per Hierarchy using Annotation

The "Table Per Hierarchy" strategy is a Hibernate inheritance mapping technique where entities of different types (subclasses) are stored in a single table. A discriminator column is used to differentiate between the types.

In this tutorial, we'll explore the "Table Per Hierarchy" inheritance strategy using annotations.

1. Setting up:

Make sure you've set up a Hibernate project with the necessary configurations and dependencies.

2. Define the Entity Classes:

Base Class (Vehicle):

This class will have a discriminator column to identify the type of vehicle - either Car or Bike.

@Entity
@Table(name = "VEHICLE")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "VEHICLE_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class Vehicle {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String manufacturer;

    // Getters, setters, constructors...
}

Here, @Inheritance is set to InheritanceType.SINGLE_TABLE, and @DiscriminatorColumn is used to specify the name and type of the discriminator column.

Concrete Subclasses (Car and Bike):

@Entity
@DiscriminatorValue("Car")
public class Car extends Vehicle {

    private int numberOfSeats;

    // Getters, setters, constructors...
}

@Entity
@DiscriminatorValue("Bike")
public class Bike extends Vehicle {

    private int saddleHeight;

    // Getters, setters, constructors...
}

Notice the @DiscriminatorValue annotation that indicates the value of the discriminator column for each entity type.

3. Persistence:

When you persist an instance of Car:

Car car = new Car();
car.setManufacturer("Toyota");
car.setNumberOfSeats(4);

session.save(car);

Hibernate will insert a new row in the VEHICLE table with a VEHICLE_TYPE of "Car".

4. Fetching:

Fetching is like usual. When you fetch a Car entity, Hibernate will get it from the VEHICLE table using the discriminator column.

Car retrievedCar = session.get(Car.class, carId);

5. Benefits & Drawbacks:

Benefits:

  • Simplified schema with a single table for all entities in the hierarchy.
  • Fetching entities is straightforward as there's only one table to query.

Drawbacks:

  • Columns specific to subclasses will be nullable in the table, which may lead to inefficient data storage.
  • If subclasses have many unique columns, the table can become wide with many nullable columns, which is not optimal.
  • Updating the inheritance hierarchy (adding/removing subclasses or changing properties) may require schema changes.

Conclusion:

The "Table Per Hierarchy" strategy is a concise and efficient way of storing entities of an inheritance hierarchy in a single table using a discriminator column. While it's a common and popular approach, always consider your application's needs and potential future changes when deciding on an inheritance mapping strategy.

  1. Hibernate table per hierarchy mapping example:

    • Table per hierarchy inheritance strategy in Hibernate allows mapping an entire hierarchy of classes to a single table.
    • Use @Entity and @Inheritance(strategy = InheritanceType.SINGLE_TABLE) annotations.
    // Parent class
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
    public abstract class Animal {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        // Common fields and methods
    }
    
    // Subclass
    @Entity
    @DiscriminatorValue("CAT")
    public class Cat extends Animal {
        private String color;
    
        // Cat-specific fields and methods
    }
    
    // Subclass
    @Entity
    @DiscriminatorValue("DOG")
    public class Dog extends Animal {
        private String breed;
    
        // Dog-specific fields and methods
    }
    
  2. Configuring table per hierarchy inheritance in Hibernate:

    • Configure table per hierarchy inheritance in Hibernate using the @Inheritance annotation with strategy = InheritanceType.SINGLE_TABLE.
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
    public abstract class Animal {
        // Common fields and methods
    }
    
  3. Mapping hierarchical classes with Hibernate annotations:

    • Map hierarchical classes using @Entity annotations for each class, @Inheritance(strategy = InheritanceType.SINGLE_TABLE), and @DiscriminatorColumn.
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
    public abstract class Animal {
        // Common fields and methods
    }
    
    @Entity
    @DiscriminatorValue("CAT")
    public class Cat extends Animal {
        // Cat-specific fields and methods
    }
    
    @Entity
    @DiscriminatorValue("DOG")
    public class Dog extends Animal {
        // Dog-specific fields and methods
    }
    
  4. Hibernate @Inheritance annotation for table per hierarchy:

    • Use @Inheritance(strategy = InheritanceType.SINGLE_TABLE) to specify the table per hierarchy inheritance strategy in Hibernate.
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
    public abstract class Animal {
        // Common fields and methods
    }
    
  5. Handling associations in table per hierarchy mapping:

    • Handle associations in table per hierarchy mapping by defining relationships in the annotated classes.
    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
    public abstract class Animal {
        // Common fields and methods
    }
    
    @Entity
    @DiscriminatorValue("CAT")
    public class Cat extends Animal {
        // Cat-specific fields and methods
    
        @ManyToOne
        @JoinColumn(name = "owner_id")
        private Person owner;
    }
    
  6. HQL queries for table per hierarchy inheritance in Hibernate:

    • Use HQL (Hibernate Query Language) for queries specific to the table per hierarchy strategy.
    String hql = "FROM Animal WHERE color = :color";
    Query query = session.createQuery(hql);
    query.setParameter("color", "black");
    List<Animal> blackAnimals = query.list();