Wednesday, July 23, 2008

Inheritance Strategy - Class per hierarchy

Hibernate supports several types of inheritance strategies in which simplest of them is "Class-per-heirarchy". In this strategy, data for all classes involved in inheritance is stored in a single table and a record is identified by discriminator column. Lets discuss this strategy with an example. Suppose there are three classes: Person, Employee, and Physician. Inheritance relationship is shown in the fig below:Person is an abstract class. So either a person will exist as Employee or Physician. Hibernate mapping for Person is shown below:


Discriminator element creates a column with name "Type", value of which will indicate whether a particular record is Employee or Physician. There is also a special property "abstract" in class element which tells that object of person can't be created.

Hibernate mapping for Employee is shown below:



"subclass" element indicates that there is a class per hierarchy strategy of inheritance between Employee and Person. "extends" property of subclass element creates relationship of "Employee" with "Person". "discriminator-value" tells hibernate to use "Employee" in discriminator column to identify all employees.

Configuration for Physician is given below:



Now lets add two Persons: one is Employee and other is Physician as shown below:

Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); Emplo
yee emp = new Employee(); emp.setName("Amer Sohail"); emp.setPay(123f); session.save(emp); Physician phy = new Physician(); phy.setName("Dr. Amer Sohail"); phy.setPay(345f);
phy.setBillingAddress("Lahore");
phy.setSpeciality("Pediatrics");
session.save(phy); session.getTransaction().commit(); session.close();


a single table with name "person" will be created in the database with following two records:


Lets retrieve the all person from database and you will observe polymorphic feature of hibernate:

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
List emp = session.createQuery("from Person emp").list();
if (emp != null && emp.size() > 0)
{
for (int index = 0; index <>
{
System.out.println("Name of employee is " +((Employee)emp.get(index)).getName());
if (emp.get(index) instanceof Person)
System.out.println("This is person");

if (emp.get(index) instanceof Employee)
System.out.println("This is Employee");

if (emp.get(index) instanceof Physician)
System.out.println("This is Physician");
}
}
session.getTransaction().commit();
session.close();


output of the code will be following:

Name of employee is Amer Sohail
This is person
This is Employee
Name of employee is Dr. Amer Sohail
This is person
This is Employee
This is Physician

As shown in output, i just retrieved "persons" but it instantiated objects of type to which they belong e.g. Amer Sohail was just an employee not a physician so hibernate created it of "Employee" type. This is really a very powerful feature of hibernate.

Now if i want to retrieve only employee not physician, then i will write the following query:


List emp = session.createQuery("from Employee emp where type = Employee").list();


I explained the strategy "class-per-heirarchy" in this blog's post. This strategy has one major drawback which you should notice while viewing records in table. It contains "nulls" against those records which are not in employee like "speciality" and "billing_address". Since DBMS has to handle null fields with a special case and it creates an impact on performance so that is the major drawback of this strategy because it will create a lot of nulls in the table. but on the other handle, no join is needed so no join cost improves the performance. Now there is very interesting situation bcz pros of this blog says it increase the performance while cons says it decreases the performance so what is the net effect. you have to wait for it for later posts in which i will compare all the strategies.

1 comment:

xavzeman said...

Hello,

Seems you seem to understand well the
table per hierarchy strategy, I would like to ask you the following.
How would you include a discriminator as part as a composite key.

Thanks.