Table per Concrete Class is one of the inheritance strategies in hibernate. If we want to keep each concrete class object of inheritance in separate tables of the database then we can proceed with the table per concrete class strategy.
- Hibernate stores each derived class object of hierarchy in a separate table of the database.
- To inform the hibernate that apply table per concrete class inheritance mapping we need to configure <union-subclass> tag under <class> tag of hbm.xml file.
- The discriminator column is optional.
In this strategy, each subclass table will have the subclass-specific attributes and the attributes inherited from the parent class.
Example for Table per Concrete Class 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.

Steps of Implementation
Step 1: Create Maven Project
- Open IntelliJ IDEA ->New Project -> Maven
- Provide GroupId and ArtifactId
Add dependencies in pom.xml
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
</dependencies>
Project Structure

Step 2: Create Database Tables
- Separate table for each class
- Subclass tables contain parent class fields
- Data is duplicated (name, age repeated)
We use three tables: Employee, P_Employee, and C_Employee. In this strategy, each subclass table stores its own fields along with all parent class properties.
CREATE TABLE `Employee` (
`Id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
`age` BIGINT(3) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
CREATE TABLE `P_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,
PRIMARY KEY (`id`)
)
CREATE TABLE `C_Employee` (
`Id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
`age` BIGINT(3) NOT NULL DEFAULT '0',
`hourlyrate` BIGINT(11) NULL DEFAULT NULL,
`duration` BIGINT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
Step 3: Create Model Classes
- Inheritance using extends
- Classes are simple POJO classes
- No Hibernate annotations used
Implementation of the Employee.java file.
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; }
}
Implementation of the P_Employee.java file.
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;
}
}
Implementation of the C_Employee.java file.
package com.exploit.model;
public class C_Employee extends Employee {
private double hourlyRate;
private double duration;
public void setDuration(double duration)
{
this.duration = duration;
}
public double getDuration() { return duration; }
public double getHourlyRate() { return hourlyRate; }
public void setHourlyRate(double hourlyRate)
{
this.hourlyRate = hourlyRate;
}
}
Step 4: Create Mapping File
Creating the mapping file for the Persistent class
- <class> defines parent class
- <union-subclass> is used for concrete class strategy
- Each subclass is mapped to its own table
- Parent properties are repeated in subclass tables
Implementation of the employee.hbm.xml file
/*package whatever //do not write package name here */
<?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">
<id name="id">
<generator class="increment"></generator>
</id>
<property name="name" column="Name"></property>
<property name="age" column="Age"></property>
<union-subclass name="com.exploit.model.P_Employee" table="P_Employee">
<property name="salary" column="Salary"></property>
</union-subclass>
<union-subclass name="com.exploit.model.C_Employee" table="C_Employee">
<property name="hourlyRate" column="HourlyRate"></property>
<property name="duration" column="Duration"></property>
</union-subclass>
</class>
</hibernate-mapping>
Step 5: Configure Hibernate
Adding the mapping of the hbm.xml file in the hibernate configuration file
- Configuration connects Hibernate to database
- Mapping file must be registered
- SQL queries can be viewed using show_sql
<?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">root</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 7: Create Main Class
- Each object stored in its respective table
- No discriminator column needed
- Hibernate handles insertion automatically
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Employee emp = new Employee();
emp.setName("John");
emp.setAge(25);
P_Employee pe = new P_Employee();
pe.setName("Alice");
pe.setAge(30);
pe.setSalary(50000);
C_Employee ce = new C_Employee();
ce.setName("Bob");
ce.setAge(28);
ce.setHourlyRate(200);
ce.setDuration(6);
session.persist(emp);
session.persist(pe);
session.persist(ce);
tx.commit();
session.close();
We have defined only one hibernate mapping (hbm) file Employee.hbm.xml, both P_Employee and C_Employee model classes are defined within one hbm.xml file. We mapped all the classes using a simple <class> tag in hbm. This is the usual way of mapping Table Per Concrete Class using XML.