Table per Hierarchy is one of the inheritance strategies in hibernate. In this strategy, the entire hierarchy is mapped to a single table. All attributes of all the classes in the hierarchy are stored in a single table. In a table per Hierarchy strategy
- A string value is stored to identify the subclass of each row
- Uses a discriminator column to store subclass type
- Configure using <sub-class> tag inside <class> in hbm.xml
Null values will be stored in the table for which there is no column applicable. A discriminator uniquely identifies the base type of the class hierarchy.
Example for Table per Hierarchy Strategy
Let's suppose we have a class Employee with subclasses as P_Employee and C_Employee. Following the class diagram and relationship of these classes.

Step 1: Create Maven Project
- Open IntelliJ IDEA -> New Project ->Maven
- Set GroupId & ArtifactId
Add Dependencies (pom.xml)
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>TablePerHierarchyXML</groupId>
<artifactId>TablePerHierarchyXML</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TablePerHierarchyXML</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
</dependencies>
</project>
Project Structure

Step 2: Create Database Table
- We have three classes: Employee (superclass), P_Employee, and C_Employee (subclasses).
- In Table Per Hierarchy strategy, all attributes of these classes are stored in a single table (Employee).
Creating Database Table to persist class Hierarchy:
CREATE TABLE `Employee` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
`age` BIGINT(3) NOT NULL DEFAULT '0',
`salary` BIGINT(11) NULL DEFAULT NULL,
`hourlyrate` BIGINT(11) NULL DEFAULT NULL,
`duration` BIGINT(11) NULL DEFAULT NULL,
`discriminator` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
)
The Employee table will store objects of all three classes Employee, P_Employee and C_Employee.
Step 3: Create Model Classes
Creating the Employee, P_Employee, and C_Employee classes for the above hierarchy:
Employee.java
package com.exploit.model;
public class Employee {
private int id;
private String name;
private int age;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
P_Employee.java
package com.exploit.model;
public class P_Employee extends Employee {
private double salary;
public double getSalary() { return salary; }
public void setSalary(double salary)
{
this.salary = salary;
}
}
C_Employee.java
package com.exploit.model;
public class C_Employee extends Employee {
private double hourlyRate;
private double duration;
public double getDuration() { return duration; }
public void setDuration(double duration)
{
this.duration = duration;
}
public double getHourlyRate() { return hourlyRate; }
public void setHourlyRate(double hourlyRate)
{
this.hourlyRate = hourlyRate;
}
}
Step 4: Create Mapping File (employee.hbm.xml)
- Creating the mapping file for the Persistent class
<class>-> defines base class<discriminator>-> identifies subclass<subclass>-> maps child classes
employee.hbm.xml.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.exploit.model">
<class name="Employee" table="Employee" discriminator-value="E">
<id name="id">
<generator class="increment"></generator>
</id>
<discriminator column="discriminator" type="string"></discriminator>
<property name="name"></property>
<property name="age"></property>
<subclass name="com.exploit.model.P_Employee" extends="Employee" discriminator-value="PE">
<property name="salary"></property>
</subclass>
<subclass name="com.exploit.model.C_Employee" extends="Employee" discriminator-value="CE">
<property name="hourlyRate"></property>
<property name="duration"></property>
</subclass>
</class>
</hibernate-mapping>
Discriminator Values:
E->EmployeePE-> P_EmployeeCE->C_Employee
Hibernate will put the appropriate discriminator values based on the record we are persisting.
Step 5: Configure Hibernate
Adding the mapping of hbm.xml file in the hibernate configuration file
dialect-> DB-specific SQL generationshow_sql->prints SQL in consolehbm2ddl.auto=update-> auto table update- Mapping file must be registered
Below is the implementation of the hibernate.cfg.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection properties -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/javainsimpleway</property>
<property name="connection.username">root</property>
<property name="connection.password">toor</property>
<!-- JDBC connection pool (using the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Format the generated Sql -->
<property name="format_sql">true</property>
<!-- Dont Drop and re-create the database schema on startup,Just update it -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="com/exploit/mapping/employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Step 6: Create Main Class
Creating the class that stores the persistent object
- Same
persist()for all classes - Hibernate automatically sets discriminator
- No need to manually insert type
Below is the implementation of the Main.java file:
package com.exploit.db;
import com.exploit.model.C_Employee;
import com.exploit.model.Employee;
import com.exploit.model.P_Employee;
import com.exploit.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class Main {
public static void main(String[] args)
{
// Get session factory using Hibernate Util class
SessionFactory sessionFactory
= HibernateUtil.getSessionFactory();
// Get session from Session factory
Session session = sessionFactory.openSession();
// Begin transaction
Transaction transaction
= session.beginTransaction();
// Creating Employee base class record
Employee employee = new Employee();
employee.setName("KirikoChan");
employee.setAge(19);
// Creating Permanent Employee subclass record
P_Employee permanentEmployee = new P_Employee();
permanentEmployee.setName("Saili.H");
permanentEmployee.setAge(20);
permanentEmployee.setSalary(30000);
// Creating Contract Employee subclass record
C_Employee contractEmployee = new C_Employee();
contractEmployee.setName("ChikkoRita");
contractEmployee.setAge(18);
contractEmployee.setDuration(8.5);
contractEmployee.setHourlyRate(2000);
// persist all the employee records
session.persist(employee);
session.persist(permanentEmployee);
session.persist(contractEmployee);
// Commit the transaction and close the session
transaction.commit();
session.close();
System.out.println(
"Employee records successfully persisted.");
}
}
Step 7: Output in Database
| id | name | age | salary | hourlyrate | duration | discriminator |
|---|---|---|---|---|---|---|
| 1 | KirikoChan | 19 | NULL | NULL | NULL | E |
| 2 | Saili.H | 20 | 30000 | NULL | NULL | PE |
| 3 | ChikkoRita | 18 | NULL | 2000 | 8.5 | CE |
This is the usual way of mapping Table Per Hierarchy using XML.