Table per hierarchy with Annotation
- 11th Feb 2017
- 0
- 9108
- advantage of table per hierarchy with annotation disadvantage of table per hierarchy with annoation example for table per hierarchy with annoation how table per hierarchy works using annoations table per hierarchy using annotation table per hierarchy using annotations Table per hierarchy with annotation in hibernate with example
Let us understand about Table Per Hierarchy with Annotation
We have already discussed Table per hierarchy with xml.
Please go through Table per hierarchy with xml article before going through the same using annotation.
Let’s create hibernate project using Annotation
Step 1
Create hibernate project
Please refer Hibernate setup in eclipse article on how to do it.
Project Structure

Step 2
Update pom.xml with Hibernate and Mysql dependencies
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>TablePerHierarchyAnnotation</groupId>
- <artifactId>TablePerHierarchyAnnotation</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>TablePerHierarchyAnnotation</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>
- <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>
- <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations -->
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.5.6-Final</version>
- </dependency>
- </dependencies>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>TablePerHierarchyAnnotation</groupId>
<artifactId>TablePerHierarchyAnnotation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>TablePerHierarchyAnnotation</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>
<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>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.6-Final</version>
</dependency>
</dependencies>
</project>
Step 3
Create Employee class
- package com.kb.model;
- import javax.persistence.Column;
- import javax.persistence.DiscriminatorColumn;
- import javax.persistence.DiscriminatorType;
- import javax.persistence.DiscriminatorValue;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Inheritance;
- import javax.persistence.InheritanceType;
- import javax.persistence.Table;
- @Entity
- @Table(name = "Employee")
- @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
- @DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
- @DiscriminatorValue(value = "E")
- public class Employee {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- @Column(name = "id")
- private int id;
- @Column(name = "name")
- private String name;
- 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;
- }
- }
package com.kb.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name = "Employee")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(value = "E")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
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;
}
}
Step 4
Create PermanentEmployee class
- package com.kb.model;
- import javax.persistence.Column;
- import javax.persistence.DiscriminatorValue;
- import javax.persistence.Entity;
- @Entity
- @DiscriminatorValue(value = "PE")
- public class PermanentEmployee extends Employee {
- @Column(name = "salary")
- private double salary;
- public double getSalary() {
- return salary;
- }
- public void setSalary(double salary) {
- this.salary = salary;
- }
- }
package com.kb.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "PE")
public class PermanentEmployee extends Employee {
@Column(name = "salary")
private double salary;
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
Step 5
Create ContractEmployee class
- package com.kb.model;
- import javax.persistence.Column;
- import javax.persistence.DiscriminatorValue;
- import javax.persistence.Entity;
- @Entity
- @DiscriminatorValue(value = "CE")
- public class ContractEmployee extends Employee {
- @Column(name = "hourlyRate")
- private double hourlyRate;
- public double getHourlyRate() {
- return hourlyRate;
- }
- public void setHourlyRate(double hourlyRate) {
- this.hourlyRate = hourlyRate;
- }
- }
package com.kb.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "CE")
public class ContractEmployee extends Employee {
@Column(name = "hourlyRate")
private double hourlyRate;
public double getHourlyRate() {
return hourlyRate;
}
public void setHourlyRate(double hourlyRate) {
this.hourlyRate = hourlyRate;
}
}
Step 6
Create hibernate.cfg.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://www.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">100</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 class="com.kb.model.Employee" />
- <mapping class="com.kb.model.ContractEmployee" />
- <mapping class="com.kb.model.PermanentEmployee" />
- </session-factory>
- </hibernate-configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.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">100</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 class="com.kb.model.Employee" />
<mapping class="com.kb.model.ContractEmployee" />
<mapping class="com.kb.model.PermanentEmployee" />
</session-factory>
</hibernate-configuration>
We have defined the entire database configuration in hibernate.cfg.xml this file
hbm2ddl.auto property is defined in the config file which helps in automatic creation of tables in the database based on the mapping.
We have also provided the mapping class names where we have added the annotations using “mapping” tag.
Step 7
Create Hibernate util class
- package com.kb.util;
- import org.hibernate.SessionFactory;
- import org.hibernate.cfg.Configuration;
- public class HibernateUtil {
- private static final SessionFactory sessionFactory = buildSessionFactory();
- private static SessionFactory buildSessionFactory() {
- try {
- // Create the SessionFactory from hibernate.cfg.xml
- return new Configuration().configure().buildSessionFactory();
- } catch (Throwable ex) {
- // Make sure you log the exception to track it
- System.err.println("SessionFactory creation failed." + ex);
- throw new ExceptionInInitializerError(ex);
- }
- }
- public static SessionFactory getSessionFactory() {
- return sessionFactory;
- }
- public static void shutdown() {
- // Optional but can be used to Close caches and connection pools
- getSessionFactory().close();
- }
- }
package com.kb.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception to track it
System.err.println("SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void shutdown() {
// Optional but can be used to Close caches and connection pools
getSessionFactory().close();
}
}
Step 8
Create main class to interact with DB
- package com.kb.db;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import com.kb.model.ContractEmployee;
- import com.kb.model.Employee;
- import com.kb.model.PermanentEmployee;
- import com.kb.util.HibernateUtil;
- public class Main {
- public static void main(String[] args) {
- //Get session factory using Hibernate Util class
- SessionFactory sf = HibernateUtil.getSessionFactory();
- //Get session from Sesson factory
- Session session = sf.openSession();
- //Begin transaction
- Transaction t=session.beginTransaction();
- //Creating Employee base class record
- Employee employee=new Employee();
- employee.setName("John");
- //Creating Permanent Employee subclass record
- PermanentEmployee permanentEmployee=new PermanentEmployee();
- permanentEmployee.setName("Jacob");
- permanentEmployee.setSalary(30000);
- //Creating Contract Employee subclass record
- ContractEmployee contractEmployee=new ContractEmployee();
- contractEmployee.setName("Raj");
- contractEmployee.setHourlyRate(2000);
- //persist all the employee records
- session.persist(employee);
- session.persist(permanentEmployee);
- session.persist(contractEmployee);
- //Commit the transaction and close the session
- t.commit();
- session.close();
- System.out.println("successfully persisted all the Employee records");
- }
- }
package com.kb.db;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.kb.model.ContractEmployee;
import com.kb.model.Employee;
import com.kb.model.PermanentEmployee;
import com.kb.util.HibernateUtil;
public class Main {
public static void main(String[] args) {
//Get session factory using Hibernate Util class
SessionFactory sf = HibernateUtil.getSessionFactory();
//Get session from Sesson factory
Session session = sf.openSession();
//Begin transaction
Transaction t=session.beginTransaction();
//Creating Employee base class record
Employee employee=new Employee();
employee.setName("John");
//Creating Permanent Employee subclass record
PermanentEmployee permanentEmployee=new PermanentEmployee();
permanentEmployee.setName("Jacob");
permanentEmployee.setSalary(30000);
//Creating Contract Employee subclass record
ContractEmployee contractEmployee=new ContractEmployee();
contractEmployee.setName("Raj");
contractEmployee.setHourlyRate(2000);
//persist all the employee records
session.persist(employee);
session.persist(permanentEmployee);
session.persist(contractEmployee);
//Commit the transaction and close the session
t.commit();
session.close();
System.out.println("successfully persisted all the Employee records");
}
}
We have created 3 records, one for each Employee, PermanentEmployee and ContractEmployee class.
When we persist these 3 records of different objects, It will be saved in a Single table.
Step 9
Run the above class to check the output
Hibernate:
create table Employee1 (
id integer not null,
discriminator varchar(255) not null,
name varchar(255),
salary double precision,
hourlyRate double precision,
primary key (id)
)
select
next_val as id_val
from
hibernate_sequence for update
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
select
next_val as id_val
from
hibernate_sequence for update
Hibernate:
update
hibernate_sequence
set
next_val= ?
where
next_val=?
Hibernate:
insert
into
Employee
(NAME, TYPE, ID)
values
(?, 'E', ?)
Hibernate:
insert
into
Employee
(NAME, SALARY, TYPE, ID)
values
(?, ?, 'PE', ?)
Hibernate:
insert
into
Employee
(NAME, HOURLYRATE, TYPE, ID)
values
(?, ?, 'CE', ?)
successfully persisted all the Employee records
We can see that Create statement is executed only once as it creates a Single table for all the classes.
We can see 3 statements for updating the auto generated primary key for ID is executed.
3 insert statements one for each object we persisted is executed.
Check the Table in MYSQL workbench
SELECT * FROM javainsimpleway.employee1;

Check Table in MYSQL console
E:\MySql_Install\bin
Mysql –u root –p
Enter password
SELECT * FROM javainsimpleway.employee1;

We can see NULL values are stored in Salary column for Contract employee and NULL values is stored in HourlyRate column for Permanent employees.
We can see NULL values stored in salary and hourlyRate columns for Employee record.
We can see that discriminator column can be used to identify the type of the record.
