Inheritance Mapping

Inheritance Mapping

In Enterprise Applications, we are able to use the data models like Object Oriented Data Model, Relational Data Model, etc. In general, Front-End applications are able to use Object Oriented Data Model to represent data and Back-End Systems are able to use Relational Data Model to represent data.

In Object Oriented Data Model, we will provide inheritance relation between entities in order to improve code Reusability.

In Relational data Model, we will use different approaches to manage inheritance kind of features at databases like maintaining all the classes properties in a single table or defining a separate table for each and every class and providing PK-FK relation between these tables.

In both the above cases, approaches are different to achieve inheritance kind of feature, it will provide Sub types mismatches between data models, it will reduce data persistency in enterprise applications.

In the above context, to improve data persistency in enterprise applications we have to use ORM implementation, Hibernate is one of the ORM implementation, it has provided the following three strategies to resolve inheritance mismatch.

  1. Table Per Class Hierarchy.
  2. Table Per Sub Class
  3. Table Per Concrete Class
1. Table Per Class Hierarchy

In Table Per Class hierarchy, we will prepare a table with the columns representing all the properties of the classes[sub classes and super class] which are existed in inheritance.

In this mechanism, when we store any sub class object then data must be stored in single table in the respective columns, if data is not available for any column then null values will be stored in the respective columns.

If we want to use Table Per Class Hierarchy in Hibernate applications then we have to use the following steps.

1. Prepare all java classes which we want to keep in Inheritance

Account.java

package com.ashok.hibernate;
/**
 * 
 * @author Ashok Kumar
 *
 */
public class Account {
	private String accNo;
	private String accName;
	private String accType;

	public String getAccNo() {
		return accNo;
	}

	public void setAccNo(String accNo) {
		this.accNo = accNo;
	}

	public String getAccName() {
		return accName;
	}

	public void setAccName(String accName) {
		this.accName = accName;
	}

	public String getAccType() {
		return accType;
	}

	public void setAccType(String accType) {
		this.accType = accType;
	}
}

StudentAccount.java

package com.ashok.hibernate;

/**
 * 
 * @author ashok.mariyala
 *
 */
public class StudentAccount extends Account {
	private String sid;
	private String sbranch;
	private int smarks;

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSbranch() {
		return sbranch;
	}

	public void setSbranch(String sbranch) {
		this.sbranch = sbranch;
	}

	public int getSmarks() {
		return smarks;
	}

	public void setSmarks(int smarks) {
		this.smarks = smarks;
	}
}

EmployeeAccount.java

package com.ashok.hibernate;

public class EmployeeAccount extends Account {
	private String eid;
	private float esal;
	private String eaddr;

	public String getEid() {
		return eid;
	}

	public void setEid(String eid) {
		this.eid = eid;
	}

	public float getEsal() {
		return esal;
	}

	public void setEsal(float esal) {
		this.esal = esal;
	}

	public String getEaddr() {
		return eaddr;
	}

	public void setEaddr(String eaddr) {
		this.eaddr = eaddr;
	}
}
2. Create a table in Database with a set of columns which are representing all properties of the classes which are existed in inheritance and discriminator column
SQL> create table account(ACCNO varchar2(5) primary key, ACCNAME varchar2(5), accType
varchar2(10), SID varchar2(5), SBRANCH varchar2(5), SMARKS number(3), EID varchar2(5),
ESAL float, EADDR varchar2(10), TYPE varchar2(10));

Where the purpose Discriminator column is to specify which sub class object data is represented by the present record.

3. Provide all sub classes configuration and discriminator column configuration in hibernate mapping file by using the following tags
<hibernate-mapping>
   <class name="--" class="--">
      ----
     <discrimintor column="--"/>
      ----
     <subclass name="--" discriminator-value="--">
      -----
     </subclass>
     ----
   </class>
</hibernate-mapping>

Where “discriminator” tag can be used to configure discriminator column, where “column” attribute in tag will take the discriminator column name which we defined in database table.

Where “subclass” tag is able to configure a single sub class and its properties, where “name” attribute will take fully qualified name of the respective sub class, where “discriminator-value” attribute will provide the exact discriminator value in order to insert or retrieve sub class object data.

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
   <class name="com.ashok.hibernate.model.Account" table="account">
      <id name="accNo" column="ACCNO" />
      <discriminator column="TYPE" type="string" />
      <property name="accName" column="ACCNAME" />
      <property name="accType" column="ACCTYPE" />
      <subclass name="com.ashok.hibernate.model.StudentAccount" discriminator-value="std">
         <property name="sid" column="SID" />
         <property name="sbranch" column="SBRANCH" />
         <property name="smarks" column="SMARKS" />
      </subclass>
      <subclass name="com.ashok.hibernate.model.EmployeeAccount" discriminator-value="emp">
         <property name="eid" column="EID" />
         <property name="esal" column="ESAL" />
         <property name="eaddr" column="EADDR" />
      </subclass>
   </class>
</hibernate-mapping>
4. In client application, Create Sub class objects with the data and perform the required database operation
SessionFactory factory = cfg.buildSessionFactory(registry);
Session session = factory.openSession();
StudentAccount sa = new StudentAccount();
sa.setAccNo("123456");
sa.setAccName("Ashok Kumar");
sa.setAccType("Savings");
sa.setSid("123");

sa.setSbranch("CS");
sa.setSmarks(77);

EmployeeAccount ea = new EmployeeAccount();
ea.setAccNo("654987");
ea.setAccName("Ashok Kumar");
ea.setAccType("Savings");
ea.setEid("E0087");
ea.setEsal(50000);
ea.setEaddr("Hyderabad");

Transaction tx = session.beginTransaction();
session.save(sa);
session.save(ea);
tx.commit();
System.out.println("Student Account Inserted Successfully");
System.out.println("Employee Account Inserted Successfully");

To represent Table Per Class Inheritance Mapping javax.persistence package has provided the following three Annotations.

  1. @Inheritance
  2. @DiscriminatorColumn
  3. @DiscriminatorValue

1. @Inheritance

This annotation is able to specify Inheritance Mapping strategy.

@Inheritance(strategy=value)

Where value may be SINGLE_TABLE constant from InheritanceType enum.

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

2. @DiscriminatorColumn

This annotation is able to represent Discriminator Column.

@DiscriminatorColumn(name ="--")

Where “name” is able to take discriminator column name.

E.g

@DiscriminatorColumn(name="TYPE")

Note

The above two annotations must be used at super class.

3. @DiscriminatorValue

It able to provide value to the discriminator column, it must be specified at sub class.

Account.java

@Entity
@Table(name="account")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class Account {
   @Id
   @Column(name="ACCNO")
   private String accNo;
   @Column(name="ACCNAME")
   private String accName;
   @Column(name="ACCTYPE")
   private String accType;
   
   // setters and getters
}

StudentAccount.java

@Entity
@DiscriminatorValue("std")
public class StudentAccount extends Account{
   @Column(name="SID")
   private String sid;
   @Column(name="SBRANCH")
   private String sbranch;
   @Column(name="SMARKS")
   private int smarks;
   
   // setters and getters
}

EmployeeAccount.java

@Entity
@DiscriminatorValue("emp")
public class EmployeeAccount extends Account{
   @Column(name="EID")
   private String eid;
   @Column(name="ESAL")
   private float esal;
   @Column(name="EADDR")
   private String eaddr;
   
   // setters and getters
}
2. Table Per Sub class

In case of “Table Per Subclass” inheritance mapping, we have to prepare a separate table for each and every class [for both super class and sub classses] existed in inheritance.

While preparing tables for sub classes we have to provide a join column which must be primary key in super class respective table and in sub class respective tables.

In hibernate applications, if we store sub class objects in database then Hibernate software has to recognize and store super class properties data in super class respective table and sub class respective data in sub class respective tables.

To achieve this requirement, Hibernate software has to recognize super class properties and sub class properties separately, for this we have to provide sub classes configuration separately in hibernate mapping file.

To provide “Table Per Subclass” inheritance mapping we have to use the following XML tags in mapping file.

<hibernate-mapping>
   <class name="--" table="--">
      ------
      <joined-subclass name="--" table="--">
         <key column="--"/>
         -----
      </join-subclass>
      ----
   </class>
</hibernate-mapping>

Where “<joined-subclass>” tag is able to configure sub class, where “name” attribute will take fully qualified name of the respective sub class and “table” attribute will take sub class respective table name.

Where “<key>” tag is able to take join key which is available in sub class respective table.

To represent “Table Per Subclass” inheritance mapping mechanism, javax.persistence package has provided the following Annotations.

1. @Inheritance

This annotation is able to represent a particular Inheritance mapping mechanism,it will use “strategy” member to take a particular inheritance mapping, where “strategy” attribute will take “JOINED” value constant from “InheritanceType” enum.

E.g

@Inheritance(strategy=InheritanceType.JOINED)

2. @PrimaryKeyJoinColumn

This annotation will be used at sub classes in order to provide Join Key column name. It will use “name” attribute to provide “join key column”.

@PrimaryKeyJoinColumn(name="TX_ID")
3. Table Per Concrete Class

In “Table per Concrete Class” inheritance mapping , we will prepare a separate table for each and every sub class containing the columns representing both the super class properties and the respective sub class properties.

In the above context, if we save any sub class object then Hibernate software has to distribute sub class objects data in the respective table and in the respective columns. To achieve this we have to use the following XML tags in hibernate mapping file.

<hibernate-mapping>
   ------
   <class name="--">
      ------
      <union-subclass name="--" table="--">
         <property name="--" column="--"/>
         ------
      </union-subclass>
      ------
   </class>
</hibernate-mapping>

Where “<union-subclass>” tag is able to provide mapping between a particular sub class and the respective table, where “name” attribute will take sub class name and table attribute will take the respective table name.

Inheritance Mapping


Scroll to top