
- Hibernate - Home
- ORM - Overview
- Hibernate - Overview
- Hibernate - Architecture
- Hibernate - Environment
- Hibernate - Configuration
- Hibernate - Sessions
- Hibernate - Persistent Class
- Hibernate - Mapping Files
- Hibernate - Mapping Types
- Hibernate - Examples
- Hibernate - O/R Mappings
- Hibernate - Cascade Types
- Hibernate - Annotations
- Hibernate - Query Language
- Hibernate - Criteria Queries
- Hibernate - Native SQL
- Hibernate - Caching
- Hibernate - Entity Lifecycle
- Hibernate - Batch Processing
- Hibernate - Interceptors
- Hibernate - ID Generator
- Hibernate - Saving Image
- Hibernate - log4j Integration
- Hibernate - Spring Integration
- Hibernate - Struts 2 Integration
- Hibernate - Web Application
- Mapping Table Examples
- Hibernate - Table Per Hiearchy
- Hibernate - Table Per Concrete Class
- Hibernate - Table Per Subclass
Hibernate - Table per Concrete Class
Introduction
In Hibernate, Java classes are mapped to DB tables. Suppose we have a class and it has several sub-classes, there are three ways Hibernate provides to map the classes to tables −
Table per Hierarchy
Table per Concrete Class
Table per Subclass
Let's discuss Table per Concrete Class in details with an example.
Table per Concrete Class
Let's say we have a class 'Shape', and it has two subclasses, 'Circle' and 'Rectangle'. In this type of mapping, we will have three tables in the database.

There are three classes in the hierarchy. Shape is the superclass and Circle and Rectangle are the child classes. Tables of subclasses will have only the fields of the subclass. In order to view all fields of sub-class, a JOIN of the superclass and subclass needs to be done.
SELECT col1, col2coln FROM superclass_table UNION SELECT col_a, col_b,..col_n FROM subclass_table;
This will select all the attributes of child class (including those that in parent class). TheUNIONoperator selects only distinct values by default. To allow duplicate values, useUNION ALL. This is why Table per Concrete is also known as Joined Subclass. To map the classes, we'll using union-subclass element in *.hbm.xml as shown below:
<class name="com.tutorialspoint.Shape" table="shape"> ... <union-subclass name="com.tutorialspoint.Circle" table="circle"> <property name="radius"></property> </union-subclass> <union-subclass name="com.tutorialspoint.Rectangle" table="rectangle"> <property name="length"></property> <property name="width"></property> </union-subclass> ...
Create Mapping Classes
Let's create the POJO classes whose data is to be persisted in the database.
Shape.java
package com.tutorialspoint; public class Shape { public int Id; public String type; public double area; public Shape() { this.type = "Shape"; } public double calculateArea() { this.area= 0; setArea(area); return area; } public int getId() { return Id; } public void setId(int i) { this.Id = i; } public String getType() { return this.type; } public double getArea() { return area; } public void setArea(double i) { area = i; } }
Circle.java
package com.tutorialspoint; import java.math.*; public class Circle extends Shape { private double radius; public Circle(double rad ) { this.radius = rad; this.type = "Circle"; } @Override public double calculateArea() { area = Math.PI * radius * radius; return area; } public void setArea() { this.area = calculateArea(); } public double getArea() { return area; } }
Rectangle.java
package com.tutorialspoint; public class Rectangle extends Shape { private double length, width; public Rectangle(double length, double width) { this.length = length; this.width = width; this.type = "Rectangle"; } @Override public double calculateArea() { return length * width; } public void setArea() { this.area = calculateArea(); } public double getArea() { return area; } }
Create Database Tables
Let us create the tables in the database. There would be three tables corresponding to above objects, you are willing to provide persistence. Consider above objects need to be stored and retrieved into the following RDBMS tables −
CREATE TABLE students.shape( id int NOT NULL, type VARCHAR(20), area float ); CREATE TABLE students.circle( id int NOT NULL, type VARCHAR(20), area float, radius float ); CREATE TABLE students.rectangle( id int NOT NULL, type VARCHAR(20), area float, length float, width float );
Create Mapping Configuration File
Now create a mapping file that instructs Hibernate how to map the defined classes to the database table.
shape.hbm.xml
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 5.3//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.tutorialspoint.Shape" table="shape"> <id name="id"> <generator class="increment"></generator> </id> <property name="type"></property> <property name="area"></property> <union-subclass name="com.tutorialspoint.Circle" table="circle"> <property name="radius"></property> </union-subclass> <union-subclass name="com.tutorialspoint.Rectangle" table="rectangle"> <property name="length"></property> <property name="width"></property> </union-subclass> </class> </hibernate-mapping>
Create Hibernate Configuration File
Now create a hibernate configuration file for database and other details.
hibernate.cfg.xml
<?xml version = "1.0" encoding = "utf-8"?> <!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hbm2ddl.auto">update</property> <property name = "hibernate.dialect"> org.hibernate.dialect.MySQL8Dialect </property> <property name = "hibernate.connection.driver_class"> com.mysql.cj.jdbc.Driver </property> <!'students' is the database name --> <property name = "hibernate.connection.url"> jdbc:mysql://localhost/students </property> <property name = "hibernate.connection.username"> root </property> <property name = "hibernate.connection.password"> guest123 </property> <!-- List of XML mapping files --> <mapping resource = "shape.hbm.xml"/> </session-factory> </hibernate-configuration>
Having property hbm2ddlauto to update will create the table if not already created during program execution.
Create Application Class
Finally, we will create our application class with the main() method to run the application. We will use this application to test Table per Concrete mapping.
TestTablePerConcrete.java
package com.tutorialspoint; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.boot.Metadata; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; public class TestTablePerConcrete{ { public static void main(String[] args) { // create a hibernate configuration StandardServiceRegistry ssr=new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build(); Metadata meta=new MetadataSources(ssr).getMetadataBuilder().build(); // get the sessionfactory and open the session SessionFactory factory=meta.getSessionFactoryBuilder().build(); Session session=factory.openSession(); // begin the transaction Transaction t=session.beginTransaction(); // create Shape instance and set details to persist Shape s1=new Shape(); s1.setType(s1.getType()); s1.setArea(s1.calculateArea()); // create Circle instance and set details to persist Circle c1=new Circle(2); c1.setType(c1.getType()); c1.setArea(); // create Rectangle instance and set details to persist Rectangle r1 = new Rectangle(3,4); r1.setType(r1.getType()); r1.setArea(); // persist all instances session.persist(s1); session.persist(c1); session.persist(r1); // commit the transaction and close the session t.commit(); session.close(); System.out.println(" Successfully persisted 3 classes. Please check your database for results."); } }
Compilation and Execution
Execute TestTablePerHierarchy binary to run the program.
Output
You would get the following result, and records would be created in the Shape table.
$java TestTablePerHierarchy Successfully persisted 3 classes. Please check your database for results.
If you check your tables, those should have the following records −
mysql> select * from shape; +----+-------+------+ | id | type | area | +----+-------+------+ | 1 | Shape | 0 | +----+-------+------+ 1 row in set (0.00 sec) mysql> select * from circle; +----+--------+-------+--------+ | id | type | area | radius | +----+--------+-------+--------+ | 1 | Circle | 12.56 | 2 | +----+--------+-------+--------+ 1 row in set (0.00 sec) mysql> select * from rectangle; +----+-----------+------+--------+-------+ | id | type | area | length | width | +----+-----------+------+--------+-------+ | 1 | Rectangle | 12 | 3 | 4 | +----+-----------+------+--------+-------+ 1 row in set (0.00 sec)