Hibernate Inheritance Example (Single Table, Table Per Class, Joined Table Strategy)

By Dhiraj Ray, 04 March,2017  
620

This article is about hibernate inheritance. Here we will be disussing about the different inheritance strategy supported by hibernate such as Single Table Strategy, Table per class strategy and Joined strategy along with their advantages and disadvantages. We will be creating code samples for each strategy and discuss about their behaviour in a great detail.

Background

As we know Java is an object oriented language and hence it supports inheritance. In java inheritance, there can be IS-A or HAS-A relationship. But when we come to any relational model, it supports only HAS-A relationship. To overcome this mimmatch hibernate provides different inheritance strategy. There are basically 3 types of hibernate strategy as follows.

1. Single Table Strategy

2. Table Per Class Strategy

3. Joined Table Strategy

hibernate-inheritance

Now let us discuss about these 3 strategies one by one. In the examples below, we have 3 different entities. The parent entity Employee.java is being extended by 2 other entities PermanentEmployee.java and ContractEmployee.java

Hibernate Single Table Strategy

In case of single table strategy, there is a single table created per inheritance hierachy. For example, we have Employee class being extended by 2 others classes but when it comes to single table strategy a single table will be created representing all the classes per inheritance hieracy and this table will contain all the data related to either Employee or ContractEmployee or PermanentEmployee.

So, the question arises as if all the entries are made in a single table then how can we identify those rows from object perspective. For this, hbernate provides a Discriminator Type(DType) column which helps to differentiate between these records. This configuration is completely annotation based. So let us define our entities and implement hibernate inheritance with Single Table Strategy.

Employee.java
@Entity @Table(name = "EMPLOYEE") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "EMP_ID") private int empId; @Column(name ="name") private String name;
PermanentEmployee.java
@Entity @Table(name="PERMANENT_EMPLOYEE") @DiscriminatorValue("PERMANENT_EMP") public class PermanentEmployee extends Employee { @Column(name="TYPE") private String type;
ContractEmployee.java
@Entity @Table(name="CONTRACT_EMPLOYEE") @DiscriminatorValue("CONTRACT_EMP") public class ContractEmployee extends Employee { @Column(name="TYPE") private String type;

@Inheritance - It is used to define the type of inheritance used in hibernate and it is defined in the parent class. If the Inheritance annotation is not specified or if no inheritance type is specified for an entity class hierarchy, the SINGLE_TABLE mapping strategy is used.

@DiscriminatorValue - This annotation is used to specify the DType column name. Here we have defined it as PERMANENT_EMP in case of PermanentEmployee.java and CONTRACT_EMPLOYEE in case of ContractEmployee.java. The DiscriminatorValue annotation can only be specified on a concrete entity class. If the DiscriminatorType is STRING, the discriminator value default is the entity name.

Defining hibernate.cfg.xml

<hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="show_sql">false</property> <mapping class="com.devglan.model.Employee"/> <mapping class="com.devglan.model.ContractEmployee"/> <mapping class="com.devglan.model.PermanentEmployee"/> </session-factory> </hibernate-configuration>

Testing Single Table Strategy

Let us define Application.java having a main method inside it to run the example and see the entries it created in the DB

Application.java
public class Application { public static void main(String[] args) { createEmployee(); } public static SessionFactory getSessionFactory() { Configuration configuration = new Configuration().configure(); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()); SessionFactory sessionFactory = configuration .buildSessionFactory(builder.build()); return sessionFactory; } public static void createEmployee() { System.out.println("****************Creating Employee*************"); Employee emp = new Employee(); emp.setName("John"); ContractEmployee contEmp = new ContractEmployee(); contEmp.setName("Mike"); contEmp.setType("CONTRACT"); PermanentEmployee perEmp = new PermanentEmployee(); perEmp.setName("Jordan"); perEmp.setType("PERMANENT"); Session session = getSessionFactory().openSession(); session.beginTransaction(); session.save(emp); session.save(contEmp); session.save(perEmp); session.getTransaction().commit(); session.close(); } }

If you run above class a java application, then you can see entries created in the DB. Since, we did not define any specific value for DTYPE column in Employee.java, by default hibernate named it as entity class name.

hibernate-single-table-strategy

Advantages of Single Table Strategy

Simplest to implement.

Only one table to deal with.

Performance wise better than all strategies because no joins or sub-selects need to be performed.

Disadvantages of Single Table Strategy

Most of the column of table are nullable so the NOT NULL constraint cannot be applied.

Tables are not normalized.

Hibernate Table Per Class Strategy

In case of table per class strategy, there are no. of tables created equivalent to exact no. of concrete entites defined in the inheritance hierachy. Hence, in our case there will be 3 different table created and each child table contains duplicate data of its parent. Hence, this strategy is not recommended. Let us redefine the same entities to accomodate table per class strategy.

hibernate-table-per-hierachy Employee.java
@Entity @Table(name = "EMPLOYEE") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Employee { @Id @GeneratedValue(strategy = GenerationType.TABLE) @Column(name = "EMP_ID") private int empId; @Column(name ="name") private String name;
ContractEmployee.java
@Entity @Table(name="CONTRACT_EMPLOYEE") public class ContractEmployee extends Employee { @Column(name="TYPE") private String type;
PermanentEmployee.java
@Entity @Table(name="PERMANENT_EMPLOYEE") public class PermanentEmployee extends Employee { @Column(name="TYPE") private String type; }

In this case there no need for the discriminator column because all entity has own table. In this strategy you use one table per class and each one has an ID. Hence, the generation type auto does not work here.

Testing Table Per Class Strategy

The Application.java remains unchanged. Run this class as a java application and check the entries created in DB as per table per class strategy.

Advantages of Table Per Class Strategy

You can define NOT NULL constraints on the table.

Disadvantages of Table Per Class Strategy

Tables are not normalized.

Select statements require more time to execute as UNION operation is applied.

Hibernate Joined Table Strategy

In this strategy, all the entries in the DB will be created in one table that is corresponding table of parent entity and the tables corresponding to the child entities will have reference to it. If this confuses you, then let us define our entities first and see the DB structure quickly to understand better.

Employee.java
@Entity @Table(name = "EMPLOYEE") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "EMP_ID") private int empId; @Column(name ="name") private String name;
ContractEmployee.java
@Entity @Table(name="CONTRACT_EMPLOYEE") @DiscriminatorValue("CONTRACT_EMP") public class ContractEmployee extends Employee { @Column(name="TYPE") private String type;
PermanentEmployee.java

@Entity @Table(name="PERMANENT_EMPLOYEE") @DiscriminatorValue("PERMANENT_EMP") public class PermanentEmployee extends Employee { @Column(name="TYPE") private String type;

The only change in the entity definition here is the type of strategy defined in Employee.java

hibernate-joined-table

Testing Joined Table Strategy

The Application.java remains unchanged. Run this class as a java application and check the entries created in DB.

Advantages of Joined Table Strategy

Tables are normalized.

You can define NOT NULL constraints.

Disadvantages of Joined Table Strategy

Low performance as it runs OUTER JOIN as well as INNER JOIN in select stements.

Conclusion

I hope this article served you whatever you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Download source

References

Hibernate Docs

JPA Docs

Suggest more topics in suggestion section or write your own article and share with your colleagues.

Is this page helpful to you? Please give us your feedback below. We would love to hear your thoughts on these articles, it will help us improve further our learning process.

Further Reading: