Saturday, 5 October 2013

Hibernate Mapping Strategy : Table Per Concrete Class with Unions

Table Per Concrete Class with Unions

Consider this Example :













As in this Example, we have an abstract class Employee which is inherited by 2 concrete class PermanentEmployee and ContractEmployee.  We have 2 tables PermanentEmployee and ContractEmployee to map this concrete class.

This mapping is very much similar to Table with Concrete class with implicit polymorphism hibernate mapping strategy except the fact that  in this strategy the database identifier is defined in abstract class which  is shared for by all concrete class in hierarchy.  Example Employee class has primary key "empId" which is shared by PermanentEmployee and ContractEmployee class.


Java Class :
Employee Class :
package com.demo.example1.pojo;

public class Employee {

private String name;
private String email;
private Long empId;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}

}

PermanentEmployee.java

package com.demo.example1.pojo;

import java.util.Date;

public class PermanentEmployee extends Employee {
private String designation;
private Date joiningDate;
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}

public Date getJoiningDate() {
return joiningDate;
}
public void setJoiningDate(Date joiningDate) {
this.joiningDate = joiningDate;
}

}

package com.demo.example1.pojo;

import java.util.Date;

public class ContractEmployee extends Employee {
private Date contractDate;

public Date getContractDate() {
return contractDate;
}

public void setContractDate(Date contractDate) {
this.contractDate = contractDate;
}
}

hbm files looks like :

<hibernate-mapping package="com.demo.example1.pojo">

<class  name="Employee" abstract="true">

<id name="empId" column="empId" type="long">
<generator class="assigned"/>
</id>

<property name="name" column="name" access="field" />
<property name="email" column="email" access="field" />

<union-subclass table="permanentemployee" name="PermanentEmployee">
<property name="designation" column="designation" />
<property name="joiningDate" column="joiningDate" type="timestamp" />
</union-subclass>

<union-subclass table="contractemployee" name="ContractEmployee">
<property name="contractDate" column="contractDate" type="timestamp" />
</union-subclass>

</class>
</hibernate-mapping>



To Run :
package com.demo.example1;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.demo.example1.pojo.ContractEmployee;
import com.demo.example1.pojo.Employee;
import com.demo.example1.pojo.Message;
import com.demo.example1.pojo.PermanentEmployee;


public class Test {
public static void main(String[] args) {

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

PermanentEmployee pm = new PermanentEmployee();
pm.setDesignation("desg") ;
pm.setEmail("permEmployee@test.com");
pm.setName("Simon") ;
pm.setEmpId(1l);
session.save(pm);


ContractEmployee cm = new ContractEmployee();
cm.setEmail("contractEmployee@test.com");
cm.setName("Peter") ;
cm.setEmpId(2l);
session.save(cm) ;

List<Employee> em = session.createQuery("from Employee").list();
System.out.println(em.size());

tx.commit();
session.close();
HibernateUtil.shutdown();
}
}


OutPut :
Hibernate:
    /* insert com.demo.example1.pojo.PermanentEmployee
        */ insert
        into
            permanentemployee
            (name, email, designation, joiningDate, empId)
        values
            (?, ?, ?, ?, ?)
Hibernate:
    /* insert com.demo.example1.pojo.ContractEmployee
        */ insert
        into
            contractemployee
            (name, email, contractDate, empId)
        values
            (?, ?, ?, ?)
Hibernate:
    /*
from
    Employee */ select
        employee0_.empId as empId1_,
        employee0_.name as name1_,
        employee0_.email as email1_,
        employee0_.designation as designat1_2_,
        employee0_.joiningDate as joiningD2_2_,
        employee0_.contractDate as contract1_3_,
        employee0_.clazz_ as clazz_
    from
        ( select
            null as contractDate,
            joiningDate,
            empId,
            email,
            name,
            designation,
            1 as clazz_
        from
            permanentemployee
        union
        select
            contractDate,
            null as joiningDate,
            empId,
            email,
            name,
            null as designation,
            2 as clazz_
        from
            contractemployee
    ) employee0_
2


Points To Note :
  1. Employee class has been declared as abstract in hbm file. Otherwise a separate table for instance of the superclass is needed. Here in this example, "assigned" id generation strategy is used which allows us to manually set the id of the instance.
  2. We cannot use Native or identity or such id generate strategy when using this Hibernate Mapping Strategy. Reason is primary key is to be shared across all union subclass of hierarchy.


No comments:

Post a Comment