top of page
Writer's pictureMIIT Training and Placements

Hibernate Inheritance: Table Per Subclass (Annotation & XML mapping)

Updated: Jul 1, 2023


Welcome to Hibernate Tutorial Series. In previous tutorials we saw how to implement Inheritance in Hibernate: One Table Per Hierarchy.


Today we will see how to implement Hibernate Inheritance: One Table per Subclass scheme.



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 Subclass example

Suppose we have a class Person with subclass Employee and Owner. Following the class diagram and relationship of these classes.




In One Table per Subclass scheme, each class persist the data in its own separate table. Thus we have 3 tables; PERSON, EMPLOYEE and OWNER to persist the class data. Note that a foreign key relationship exists between the subclass tables and super class table. Thus the common data is stored in PERSON table and subclass specific fields are stored in EMPLOYEE and OWNER tables.


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


Advantage

  • Using this hierarchy, does not require complex changes to the database schema when a single parent class is modified.

  • It works well with shallow hierarchy.


Disadvantage

  • As the hierarchy grows, it may result in poor performance.

  • The number of joins required to construct a subclass also grows.



Create Database Table to persist Subclass

CREATE TABLE `person` (
	`person_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
	`firstname` VARCHAR(50) NOT NULL DEFAULT '0',
	`lastname` VARCHAR(50) NOT NULL DEFAULT '0',
	PRIMARY KEY (`person_id`)
)

CREATE TABLE `employee` (
	`person_id` BIGINT(10) NOT NULL,
	`joining_date` DATE NULL DEFAULT NULL,
	`department_name` VARCHAR(50) NULL DEFAULT NULL,
	PRIMARY KEY (`person_id`),
	CONSTRAINT `FK_PERSON` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
)

CREATE TABLE `owner` (
	`person_id` BIGINT(20) NOT NULL DEFAULT '0',
	`stocks` BIGINT(11) NULL DEFAULT NULL,
	`partnership_stake` BIGINT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`person_id`),
	CONSTRAINT `FK_PERSON2` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
)

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



Hibernate Inheritance: XML Mapping

Following is the example where we map Person, Employee and Owner 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: Owner.java

package net.miit.hibernate;

public class Owner extends Person {

		private Long stocks;
		private Long partnershipStake;

	// 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">
		<id name="personId" column="PERSON_ID">
			<generator class="native" />
		</id>

		<property name="firstname" />
		<property name="lastname" column="lastname" />

		<joined-subclass name="Employee" extends="Person">
				<key column="person_id" />
				<property name="departmentName" column="department_name" />
				<property name="joiningDate" type="date" column="joining_date" />
		</joined-subclass>
		<joined-subclass name="Owner" extends="Person">
				<key column="person_id" />
				<property name="stocks" column="stocks" />
				<property name="partnershipStake" column="partnership_stake" />
		</joined-subclass>
	</class>
</hibernate-mapping>

Code language: Java (java)

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.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.JOINED)
public class Person {

	@Id@GeneratedValue@Column(name = "PERSON_ID")
	private Long personId;
	
	@Column(name = "FIRSTNAME")
	private String firstname;
	
	@Column(name = "LASTNAME")
	private String lastname;
	
	public Person() {
	
	}
	public Person(String firstname, String lastname) {
		this.firstname = firstname;
		this.lastname = lastname;
	}

	// Getter and 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.


@InheritanceType – Defines inheritance strategy options. JOINED is a strategy in which fields that are specific to a subclass are mapped to a separate table than the fields that are common to the parent class, and a join is performed to instantiate the subclass. Thus fields of Employee (joining_date, department) and Owner (stocks etc) are mapped to their respective tables.


File: Employee.java

package net.miit.hibernate;

import java.util.Date;

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

@Entity@Table(name="EMPLOYEE")
@PrimaryKeyJoinColumn(name="PERSON_ID")
public class Employee extends Person {

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

	public Employee() {
	}
	
	public Employee(String firstname, String lastname, String departmentName, Date joiningDate) {
		
		super(firstname, lastname);
		
		this.departmentName = departmentName;
		this.joiningDate = joiningDate;
	}

	// Getter and Setter methods, 
}

Code language: Java (java)

File: Owner.java

package net.miit.hibernate;

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

@Entity@Table(name="OWNER")
@PrimaryKeyJoinColumn(name="PERSON_ID")
public class Owner extends Person {

	@Column(name="stocks")
	private Long stocks;
	
	@Column(name="partnership_stake")
	private Long partnershipStake;

	public Owner() {
	}
	
	public Owner(String firstname, String lastname, Long stocks, Long partnershipStake) {
		
		super(firstname, lastname);
		
		this.stocks = stocks;
		this.partnershipStake = partnershipStake;
	}

	// Getter and Setter methods, 
}

Code language: Java (java)

Both Employee and Owner classes are child of Person class. Thus while specifying the mappings, we used @PrimaryKeyJoinColumn to map it to parent table.


@PrimaryKeyJoinColumn – This annotation specifies a primary key column that is used as a foreign key to join to another table.


It is used to join the primary table of an entity subclass in the JOINED mapping strategy to the primary table of its superclass; it is used within a SecondaryTable annotation to join a secondary table to a primary table; and it may be used in a OneToOne mapping in which the primary key of the referencing entity is used as a foreign key to the referenced entity.


If no PrimaryKeyJoinColumn annotation is specified for a subclass in the JOINED mapping strategy, the foreign key columns are assumed to have the same names as the primary key columns of the primary table of the superclass


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);

		Owner owner = new Owner("Bill", "Gates", 300L, 20L);
		session.save(owner);

		
		session.getTransaction().commit();
		session.close();

	}
}

Code language: Java (java)

The Main class is used to persist Person, Employee and Owner object instances. Note that these classes are persisted in different tables.


Output

Hibernate: insert into PERSON (firstname, lastname) values (?, ?)
Hibernate: insert into PERSON (firstname, lastname) values (?, ?)
Hibernate: insert into Employee (department_name, joining_date, person_id) values (?, ?, ?)
Hibernate: insert into PERSON (firstname, lastname) values (?, ?)
Hibernate: insert into Owner (stocks, partnership_stake, person_id) values (?, ?, ?)

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



47 views0 comments

Recent Posts

See All

Comments


bottom of page