top of page

Hibernate Inheritance: Table Per Class Hierarchy (Annotation & XML Mapping)

Writer's picture: MIIT Training and PlacementsMIIT Training and Placements

Welcome to Hibernate Tutorial Series. In previous tutorials we saw how to implement Relationship Mapping in Hibernate. We saw different mapping techniques like One to Many, Many to Many using both Annotations and XML mapping.

Today we will see how the Inheritance is managed in Hibernate.



Introduction to Inheritance in Hibernate

Java is an object oriented language. It is possible to implement Inheritance in Java. Inheritance is one of the most visible facets of Object-relational mismatch. Object oriented systems can model both “is a” and “has a” relationship. Relational model supports only “has a” relationship between two entities. Hibernate can help you map such Objects with relational tables. But you need to choose certain mapping strategy based on your needs.



One Table Per Class Hierarchy example

Suppose we have a class Person with subclass Employee. The properties of each class are:

* class Person
	- firstname
	- lastname

* class Employee
	- joining_date
	- department_name

In One Table per Class Hierarchy scheme, we store all the class hierarchy in a single SQL table. A discriminator is a key to uniquely identify the base type of the class hierarchy.


Following are the advantages and disadvantages of One Table per Class Hierarchy scheme.


Advantage

  • This hierarchy offers the best performance even for in the deep hierarchy since single select may suffice.


Disadvantage


  • Changes to members of the hierarchy require column to be altered, added or removed from the table.


Create Database Table to persist Class Hierarchy

CREATE TABLE `person` (
	`person_id` BIGINT(10) NOT NULL AUTO_INCREMENT,
	`firstname` VARCHAR(50) NULL DEFAULT NULL,
	`lastname` VARCHAR(50) NULL DEFAULT NULL,
	`joining_date` DATE NULL DEFAULT NULL,
	`department_name` VARCHAR(50) NULL DEFAULT NULL,
	`discriminator` VARCHAR(20) NOT NULL,
	PRIMARY KEY (`person_id`)
)
Code language: SQL (Structured Query Language) (sql)

The PERSON table will store both Employee and Person objects.



Hibernate Inheritance: XML Mapping

Following is the example where we map Employee and Person entity classes using XML mapping.


File: Person.java

package net.miit.hibernate;

public class Person {

	private Long personId;
	private String firstname;
	private String lastname;

	// Constructors and Getter/Setter methods, 
}

Code language: Java (java)

File: Employee.java

package net.miit.hibernate;

import java.util.Date;

public class Employee extends Person {

	private Date joiningDate;
	private String departmentName;

	// Constructors and Getter/Setter methods, 
}

Code language: Java (java)

File: Person.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="net.miit.hibernate"><class name="Person" table="PERSON" discriminator-value="P"><id name="personId" column="PERSON_ID"><generator class="native" /></id><discriminator column="DISCRIMINATOR" type="string" /><property name="firstname" /><property name="lastname" column="lastname" /><subclass name="Employee" extends="Person" discriminator-value="E"><property name="departmentName" column="department_name" /><property name="joiningDate" type="date" column="joining_date" /></subclass></class></hibernate-mapping>
Code language: HTML, XML (xml)

Note that we have defined only one hibernate mapping (hbm) file Person.hbm.xml. Both Person and Employee model class are defined within one hbm file.


<discriminator> tag is used to define the discriminator column.


<subclass> tag is used to map the subclass Employee. Note that we have not used the usual <class> tag to map Employee as it falls below in the hierarchy tree.


The discriminator-value for Person is defined as “P” and that for Employee is defined “E”, Thus, when Hibernate will persist the data for person or employee it will accordingly populate this value.



Hibernate Inheritance: Annotation Mapping

Following is the example where we map Employee and Person entity classes using JPA Annotations.


File: Person.java

package net.miit.hibernate;

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.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;


@Entity@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="discriminator",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
public class Person {

	@Id@GeneratedValue@Column(name = "PERSON_ID")
	private Long personId;
	
	@Column(name = "FIRSTNAME")
	private String firstname;
	
	@Column(name = "LASTNAME")
	private String lastname;
	
	// Constructors and Getter/Setter methods, 
}

Code language: Java (java)

The Person class is the root of hierarchy. Hence we have used some annotations to make it as the root.


@Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.


@DiscriminatorColumn – Is used to define the discriminator column for the SINGLE_TABLE and JOINED inheritance mapping strategies. The strategy and the discriminator column are only specified in the root of an entity class hierarchy or sub hierarchy in which a different inheritance strategy is applied


If the @DiscriminatorColumn annotation is missing, and a discriminator column is required, the name of the discriminator column defaults to "DTYPE" and the discriminator type to DiscriminatorType.STRING.


@DiscriminatorValue – Is used to specify the value of the discriminator column for entities of the given type. The DiscriminatorValue annotation can only be specified on a concrete entity class. If the DiscriminatorValue annotation is not specified and a discriminator column is used, a provider-specific function will be used to generate a value representing the entity type. If the DiscriminatorType is STRING, the discriminator value default is the entity name.


The inheritance strategy and the discriminator column are only specified in the root of an entity class hierarchy or subhierarchy in which a different inheritance strategy is applied. The discriminator value, if not defaulted, should be specified for each entity class in the hierarchy.



File: Employee.java

package net.miit.hibernate;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity@Table(name="PERSON")
@DiscriminatorValue("E")
public class Employee extends Person {

	@Column(name="joining_date")
	private Date joiningDate;
	
	@Column(name="department_name")
	private String departmentName;

	// Constructors and Getter/Setter methods, 
}

Code language: Java (java)

Employee class is child of Person class. Thus while specifying the mappings, we used @DiscriminatorValue to specify discriminator value. In our case “E” will be persisted in discriminator column.


Main class

package net.miit.hibernate;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class Main {

	public static void main(String[] args) {

		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session session = sf.openSession();
		session.beginTransaction();

		
		Person person = new Person("Steve", "Balmer");
		session.save(person);

		Employee employee = new Employee("James", "Gosling", "Marketing", new Date());
		session.save(employee);
		
		session.getTransaction().commit();
		session.close();

	}
}

Code language: Java (java)

The Main class is used to persist Person and Employee object instance. Note that both these classes are persisted in same table PERSON. The discriminator column is used to distinguished between the entities.


Output

Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, discriminator) values (?, ?, 'P')
Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, department_name, joining_date, discriminator) values (?, ?, ?, ?, 'E')

Code language: SQL (Structured Query Language) (sql)




116 views0 comments

Recent Posts

See All

댓글


bottom of page