Table Per Class Example Hibernate


Table Per Class Hierarchy

Note: Before going through this application, it is advised to read Hibernate Mapping Tutorial.

In this Table Per Class style, only one table is created with sufficient columns to accommodate all the properties of each class involved in hierarchy. Because all the records of each class are available in a single table, to differentiate which record belongs to which class, we create one extra column known as discriminator column. Each class identified by some name (say, alias name written in the mapping file) and this name is stored in the discriminator column.

In this Table Per Class approach, the Programmer should be careful that super class and subclass variables should not conflict (should not be the same). If such a situation comes, rename the field either in super class or subclass. In the table, for each record some columns will be empty; those columns for which the particular Java class does not have fields.

Table EMPTABLE does not exist. Let hbm2ddl.auto create it.

Let us write one client program for three bean programs – Employee, PermanentEmployee, TemporaryEmployee and two XML files – Employee.hbm.xml and hibernate.cfg.xml. Total 6 files.

Following is the Hierarchy of classes involved. Output screens are shown the end of this notes.

Table Per Class

Let us create Java classes for the above hierarchy.

1. File Name: Employee.java

public class Employee {
	
  private short empId;
  private String empName;

  public Employee() {
    // TODO Auto-generated constructor stub
  }
  public short getEmpId() {
    return empId;
  }
  public void setEmpId(short empId) {
    this.empId = empId;
  }
  public String getEmpName() {
    return empName;
  }
  public void setEmpName(String empName) {
    this.empName = empName;
  }   
}

2. File Name: PermanentEmployee.java

public class PermanentEmployee extends Employee {
  private String designation;
  private String department;

  public PermanentEmployee() {
    // TODO Auto-generated constructor stub
  }
  public String getDesignation() {
    return designation;
  }
  public void setDesignation(String designation) {
    this.designation = designation;
  }
  public String getDepartment() {
    return department;
  }
  public void setDepartment(String department) {
    this.department = department;
  }   
}

3. File Name: TemporaryEmployee.java

public class TemporaryEmployee extends Employee {
	
  private short workingDays;
  String contractorName;

  public TemporaryEmployee() {
    // TODO Auto-generated constructor stub
  }
  public short getWorkingDays() {
    return workingDays;
  }
  public void setWorkingDays(short workingDays) {
    this.workingDays = workingDays;
  }
  public String getContractorName() {
    return contractorName;
  }
  public void setContractorName(String contractorName) {
    this.contractorName = contractorName;
  }    
} 

4. File Name: hibernate.cfg.xml






  org.hibernate.dialect.Oracle9Dialect
  jdbc:oracle:thin:@localhost:1521:orcl1
  scott
  tiger
  oracle.jdbc.driver.OracleDriver
  SNRaoConnection
  update
  true

  



5. File Name: Employee.hbm.file






  
  
  

  
    
    
  

  
    
    
  
        


6. Client Program: TablePerClassHierarchy.java

import org.hibernate.*;   
import org.hibernate.cfg.*;

public class TablePerClassHierarchy {
  public static void main(String[] args) 
  {
    Configuration cfg = new Configuration();
    cfg.configure("hibernate.cfg.xml"); 
		 
    SessionFactory sf = cfg.buildSessionFactory();
    Session session = sf.openSession();
                                          // create two objects of PermanentEmployee
    PermanentEmployee p1 = new PermanentEmployee();
    p1.setEmpId((short)100);
    p1.setEmpName("S N Rao");
    p1.setDesignation("Chemist");
    p1.setDepartment("Drugs");
		
    PermanentEmployee p2 = new PermanentEmployee();
    p2.setEmpId((short)101);
    p2.setEmpName("Sridhar");
    p2.setDesignation("Foreman");
    p2.setDepartment("Chemicals");
                                          // create two objects of TemporaryEmployee
    TemporaryEmployee t1 = new TemporaryEmployee();
    t1.setEmpId((short)102);
    t1.setEmpName("Jyostna");
    t1.setWorkingDays((short)28);
    t1.setContractorName("Raju");
		        
    TemporaryEmployee t2 = new TemporaryEmployee();
    t2.setEmpId((short)103);
    t2.setEmpName("Jyothi");
    t2.setWorkingDays((short)22);
    t2.setContractorName("Pratap");
                                          // now save all four objects
    Transaction tx = session.beginTransaction();
    session.save(p1);   session.save(t1);
    session.save(p2);   session.save(t2);

    tx.commit();  session.close();   sf.close();
    System.out.println("Objects saved");
  }
}

Table Per Class

Screenshot of MyEclipse Console. Observe four SQL statements are executed by Hibernate to persist four Java objects.

Table Per Class

  1. Observe, the table structure created automatically by Hibernate for the fields of three bean classes. For short data type, it is NUMBER(5) column type is created.
  2. Observe the four records. Some records columns are empty. For example, for temporary employee, columns DESIGNATION and DEPARTMENT are empty as TemporaryEmployee does not contain these fields.
  3. There is a limitation of mapping strategy with table-per-class. Certain columns declared by the subclasses, such as designation etc., cannot have NOT NULL constraints.
  4. Observe the discriminator (DIS) column. It is very special for table-per-class-hierarchy.

Let us write one more client program to retrieve the records separately of permanent and temporary employee.

FileName: RetrievingRecords.java

import java.util.List;  
import org.hibernate.Query;  
import org.hibernate.Session;
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;

public class RetrievingRecords 
{
  public static void main(String[] args) 
  {
    Configuration c= new Configuration();
    c.configure("/hibernate.cfg.xml");
    SessionFactory sf=c.buildSessionFactory();
    Session s=sf.openSession();

    Query q = s.createQuery("FROM PermanentEmployee");
    List myList = q.list();
    for(PermanentEmployee p1 :myList) 
    {
      System.out.println(p1.getEmpId()+ ", " + p1.getEmpName() + ", " + p1.getDesignation() + ", " + p1.getDepartment());
    }

    Query q1 = s.createQuery("FROM TemporaryEmployee");
    List yourList = q1.list();
    for(TemporaryEmployee t1 : yourList)  
    {
      System.out.println(t1.getEmpId()+ ", " + t1.getEmpName() + ", " + t1.getWorkingDays() + ", " + t1.getContractorName());
    }
  }
}

Table Per Class

Observe all the records of PermanentEmployee are retrieved once (only one SQL statement is executed) and similarly for TemporaryEmployee.

Leave a Comment

Your email address will not be published.