Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Table Per Concrete Class Using Annotation

In Hibernate, the "Table Per Concrete Class" strategy is one of the ways to map an inheritance hierarchy of entities to relational tables. Under this strategy, every concrete subclass has its own table that includes columns for all of its inherited attributes.

In this tutorial, we'll look into the "Table Per Concrete Class" 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 (Animal):

This class is a simple POJO with an id and name attribute.

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Animal {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    // Getters, setters, constructors...
}

Notice the @Inheritance annotation with InheritanceType.TABLE_PER_CLASS which indicates Hibernate should use the "Table Per Concrete Class" strategy.

Concrete Subclasses (Cat and Dog):

@Entity
public class Cat extends Animal {

    private String purringVolume;

    // Getters, setters, constructors...
}

@Entity
public class Dog extends Animal {

    private String barkPitch;

    // Getters, setters, constructors...
}

3. Persistence:

When you persist an instance of Cat:

Cat cat = new Cat();
cat.setName("Whiskers");
cat.setPurringVolume("Soft");

session.save(cat);

Hibernate will create a new row in the Cat table with all the attributes of Cat including those inherited from Animal.

4. Fetching:

Fetching is straightforward. When you fetch a Cat entity, Hibernate will get it from the Cat table.

Cat retrievedCat = session.get(Cat.class, catId);

5. Benefits & Drawbacks:

Benefits:

  • The schema is normalized.
  • No need for nullable columns in child tables, as each table only contains columns for the attributes declared in that class.

Drawbacks:

  • Polymorphic queries (queries that involve base and subclasses) can be less efficient, as they may require unions across multiple tables.
  • Inserting a subclass entity requires an insert statement for the table corresponding to that subclass.

Conclusion:

The "Table Per Concrete Class" strategy is a straightforward approach that maps each concrete class to its table. While it does offer a clean schema, it can be less efficient in terms of polymorphic operations compared to other inheritance mapping strategies like "Single Table" or "Table Per Class Hierarchy". Always choose the inheritance strategy based on the specific needs and performance considerations of your application.

  1. Hibernate table per concrete class mapping example:

    • Table per concrete class inheritance strategy in Hibernate allows each concrete class to have its own table.
    • Use @Entity and @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) annotations.
    // Abstract parent class
    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstract class Animal {
        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        private Long id;
    
        // Other fields and methods
    }
    
    // Concrete subclass
    @Entity
    public class Cat extends Animal {
        private String color;
    
        // Cat-specific fields and methods
    }
    
    // Concrete subclass
    @Entity
    public class Dog extends Animal {
        private String breed;
    
        // Dog-specific fields and methods
    }
    
  2. Configuring table per concrete class inheritance in Hibernate:

    • Configure table per concrete class inheritance using the @Inheritance annotation with strategy = InheritanceType.TABLE_PER_CLASS.
    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstract class Animal {
        // Common fields and methods
    }
    
  3. Mapping concrete classes with Hibernate annotations:

    • Map concrete classes using @Entity annotations for each class and @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) at the superclass level.
    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstract class Animal {
        // Common fields and methods
    }
    
    @Entity
    public class Cat extends Animal {
        // Cat-specific fields and methods
    }
    
    @Entity
    public class Dog extends Animal {
        // Dog-specific fields and methods
    }
    
  4. Hibernate @Inheritance annotation for table per concrete class:

    • Use @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) to specify the table per concrete class inheritance strategy in Hibernate.
    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstract class Animal {
        // Common fields and methods
    }
    
  5. Handling associations in table per concrete class mapping:

    • Handle associations in table per concrete class mapping by defining relationships in the concrete classes.
    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
    public abstract class Animal {
        // Common fields and methods
    }
    
    @Entity
    public class Cage {
        @OneToMany(mappedBy = "cage")
        private List<Animal> animals;
    }
    
  6. HQL queries for table per concrete class inheritance in Hibernate:

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