Table Inheritence
We can map the inheritance hierarchy classes with the table of the database. There are three inheritance mapping strategies defined in the hibernate:
Table Per Hierarchy using xml file
employee.hbm.xml:
<hibernate-mapping
package="com.practice.singletable.xml.approach" auto-import="false">
<class name="Employee" table="employee3" discriminator-value="E">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<discriminator column="type" type="string" />
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<subclass name="PermanentEmployee" discriminator-value="P">
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</subclass>
<subclass name="ContractEmployee" discriminator-value="C">
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</subclass>
</class>
</hibernate-mapping>
Table Per Hierarchy using Annotation
//File: Employee.java
@Entity(name = "com.practice.singletable.annotation.approach.Employee")
@Table(name = "employee4")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value="E")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String department;
private String designation;
// setters and getters ..............
}
// File: PermanentEmployee.java
@Entity(name="com.practice.singletable.annotation.approach.PermanentEmployee")
@DiscriminatorValue(value="P")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters..........
}
// File: ContractEmployee.java
@Entity(name = "com.practice.singletable.annotation.approach.ContractEmployee")
@DiscriminatorValue(value = "C")
public class ContractEmployee extends Employee {
@Column(name = "pay_per_hour")
private long payPerHour;
@Column(name = "contract_date")
private LocalDate contractDate;
// setters and getters..................
}
Table Per Concrete class using xml file
employee.hbm.xml
<hibernate-mapping
package="com.practice.tableperclass.xml.approach" auto-import="false">
<class name="Employee" table="employee1">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<!-- First way of IS-A relationship:: Choosing one table to one class -->
<union-subclass name="PermanentEmployee"
table="p_employee1">
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</union-subclass>
<!-- First way of IS-A relationship:: Choosing one table to one class -->
<union-subclass name="ContractEmployee"
table="c_employee1">
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</union-subclass>
</class>
</hibernate-mapping>
Table Per Concrete class using Annotation
//File: Employee.java
@Entity(name="com.practice.tableperclass.annotation.approach.Employee")
@Table(name="employee2")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="employee_id")
private Integer employeeId;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String department;
private String designation;
// setters and getters.......................
}
// File: PermanentEmployee.java
@Entity(name="com.practice.tableperclass.annotation.approach.PermanentEmployee")
@Table(name="p_employee2")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters....................
}
// File: ContractEmployee.java
@Entity(name="com.practice.tableperclass.annotation.approach.ContractEmployee")
@Table(name="c_employee2")
public class ContractEmployee extends Employee {
@Column(name="pay_per_hour")
private long payPerHour;
@Column(name="contract_date")
private LocalDate contractDate;
// setters..getters................................
}
Table Per Subclass using xml file
employee.hbm.xml
<hibernate-mapping
package="com.practice.joinedtable.xml.approach" auto-import="false">
<class name="Employee" table="employee5">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<joined-subclass name="PermanentEmployee"
table="p_employee5">
<key column="employee_id" />
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</joined-subclass>
<joined-subclass name="ContractEmployee"
table="c_employee5">
<key column="employee_id" />
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</joined-subclass>
</class>
</hibernate-mapping>
Table Per Subclass using Annotation
@Entity(name = "com.practice.joinedtable.annotation.approach.Employee")
@Table(name = "employee6")
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String department;
private String designation;
// setters and getters.................
}
// File:PermanentEmployee.java
@Entity(name="com.practice.joinedtable.annotation.approach.PermanentEmployee")
@Table(name="p_employee6")
@PrimaryKeyJoinColumn(name="employee_id")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters
}
// ContractEmployee.java
@Entity(name = "com.practice.joinedtable.annotation.approach.ContractEmployee")
@Table(name="c_employee6")
@PrimaryKeyJoinColumn(name="employee_id")
public class ContractEmployee extends Employee {
@Column(name = "pay_per_hour")
private long payPerHour;
@Column(name = "contract_date")
private LocalDate contractDate;
// setters and getters
}
Client Program to test the code M1.java
When no explicit inheritance strategy is registered, Hibernate/JPA will choose the SINGLE_TABLE inheritance strategy by default.
- Table Per Hierarchy
- Table Per Concrete class
- Table Per Subclass
Table Per Hierarchy
In table per hierarchy mapping, single table is required to map the whole hierarchy, an extra column (known as discriminator column) is added to identify the class. But nullable values are stored in the table .
employee.hbm.xml:
<hibernate-mapping
package="com.practice.singletable.xml.approach" auto-import="false">
<class name="Employee" table="employee3" discriminator-value="E">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<discriminator column="type" type="string" />
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<subclass name="PermanentEmployee" discriminator-value="P">
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</subclass>
<subclass name="ContractEmployee" discriminator-value="C">
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</subclass>
</class>
</hibernate-mapping>
Table Per Hierarchy using Annotation
//File: Employee.java
@Entity(name = "com.practice.singletable.annotation.approach.Employee")
@Table(name = "employee4")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue(value="E")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String department;
private String designation;
// setters and getters ..............
}
// File: PermanentEmployee.java
@Entity(name="com.practice.singletable.annotation.approach.PermanentEmployee")
@DiscriminatorValue(value="P")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters..........
}
// File: ContractEmployee.java
@Entity(name = "com.practice.singletable.annotation.approach.ContractEmployee")
@DiscriminatorValue(value = "C")
public class ContractEmployee extends Employee {
@Column(name = "pay_per_hour")
private long payPerHour;
@Column(name = "contract_date")
private LocalDate contractDate;
// setters and getters..................
}
Table Per Concrete class
In case of table per concrete class, tables are created as per class. But duplicate column is added in subclass tables.
employee.hbm.xml
<hibernate-mapping
package="com.practice.tableperclass.xml.approach" auto-import="false">
<class name="Employee" table="employee1">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<!-- First way of IS-A relationship:: Choosing one table to one class -->
<union-subclass name="PermanentEmployee"
table="p_employee1">
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</union-subclass>
<!-- First way of IS-A relationship:: Choosing one table to one class -->
<union-subclass name="ContractEmployee"
table="c_employee1">
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</union-subclass>
</class>
</hibernate-mapping>
Table Per Concrete class using Annotation
//File: Employee.java
@Entity(name="com.practice.tableperclass.annotation.approach.Employee")
@Table(name="employee2")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="employee_id")
private Integer employeeId;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
private String department;
private String designation;
// setters and getters.......................
}
// File: PermanentEmployee.java
@Entity(name="com.practice.tableperclass.annotation.approach.PermanentEmployee")
@Table(name="p_employee2")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters....................
}
// File: ContractEmployee.java
@Entity(name="com.practice.tableperclass.annotation.approach.ContractEmployee")
@Table(name="c_employee2")
public class ContractEmployee extends Employee {
@Column(name="pay_per_hour")
private long payPerHour;
@Column(name="contract_date")
private LocalDate contractDate;
// setters..getters................................
}
Table Per Subclass
In this strategy, tables are created as per class but related by foreign key. So there are no duplicate columns.
employee.hbm.xml
<hibernate-mapping
package="com.practice.joinedtable.xml.approach" auto-import="false">
<class name="Employee" table="employee5">
<id name="employeeId" column="employee_id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" />
<property name="lastName" column="last_name" />
<property name="department" />
<property name="designation" />
<joined-subclass name="PermanentEmployee"
table="p_employee5">
<key column="employee_id" />
<property name="salary" column="salary" />
<property name="bonus" column="bonus" />
</joined-subclass>
<joined-subclass name="ContractEmployee"
table="c_employee5">
<key column="employee_id" />
<property name="payPerHour" column="pay_per_hour" />
<property name="contractDate" column="contract_date" />
</joined-subclass>
</class>
</hibernate-mapping>
Table Per Subclass using Annotation
@Entity(name = "com.practice.joinedtable.annotation.approach.Employee")
@Table(name = "employee6")
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
private String department;
private String designation;
// setters and getters.................
}
// File:PermanentEmployee.java
@Entity(name="com.practice.joinedtable.annotation.approach.PermanentEmployee")
@Table(name="p_employee6")
@PrimaryKeyJoinColumn(name="employee_id")
public class PermanentEmployee extends Employee {
private long salary;
private long bonus;
// setters and getters
}
// ContractEmployee.java
@Entity(name = "com.practice.joinedtable.annotation.approach.ContractEmployee")
@Table(name="c_employee6")
@PrimaryKeyJoinColumn(name="employee_id")
public class ContractEmployee extends Employee {
@Column(name = "pay_per_hour")
private long payPerHour;
@Column(name = "contract_date")
private LocalDate contractDate;
// setters and getters
}
Client Program to test the code M1.java
When no explicit inheritance strategy is registered, Hibernate/JPA will choose the SINGLE_TABLE inheritance strategy by default.
Comments
Post a Comment