Hibernate Framework : ORM Tool :: Hibernate Polymorphic/Inheritance Mapping
- Polymorphic Mapping Intro
- Table Per Class Hierarchy / <subclass> tag Example
- Table Per Sub Class / <joined-subclass> tag Example
- Table Per Concrete Class / <union-subclass> tag or <class> tag Example
- Download Examples
Polymorphic Mapping Intro |
Understanding Inheritance Mapping
The three strategies Hibernate supports the three basic inheritance mapping strategies:
- table per class hierarchy
- table per subclass
- table per concrete class
1.table per class hierarchy
Suppose we have an interface Payment with the implementors CreditCardPayment, CashPayment, and ChequePayment.The table per hierarchy mapping would display in the following way:
<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
< generator class="native"/>
</id>
< discriminator column="PAYMENT_TYPE" type="string"/>
<property name="amount" column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
< property name="creditCardType" column="CCTYPE"/>
...
< /subclass>
<subclass name="CashPayment" discriminator-value="CASH">
...
< /subclass>
<subclass name="ChequePayment" discriminator-value="CHEQUE">
...
< /subclass>
</class>
Exactly one table is required. There is a limitation of this mapping strategy: columns declared by the subclasses, such as CCTYPE, cannot have NOT NULL constraints.
2. table per subclass
A table per subclass mapping looks like this
<class name="Payment" table="PAYMENT">
<id name="id" type="long" column="PAYMENT_ID">
< generator class="native"/>
</id>
<property name="amount" column="AMOUNT"/>
...
< joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
< property name="creditCardType" column="CCTYPE"/>
...
< /joined-subclass>
< joined-subclass name="CashPayment" table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
< /joined-subclass>
< joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
<key column="PAYMENT_ID"/>
...
< /joined-subclass>
</class>
Four tables are required. The three subclass tables have primary key associations to the superclass table so the relational model is actually a one-to-one association.
3. table per concrete class
There are two ways we can map the table per concrete class strategy. First, you can use <union-subclass>.
<class name="Payment">
<id name="id" type="long" column="PAYMENT_ID">
< generator class="sequence"/>
</id>
<property name="amount" column="AMOUNT"/>
...
< union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
< property name="creditCardType" column="CCTYPE"/>
...
< /union-subclass>
< union-subclass name="CashPayment" table="CASH_PAYMENT">
...
< /union-subclass>
< union-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
...
< /union-subclass>
</class>
- Three tables are involved for the subclasses.
- Each table defines columns for all properties of the class, including inherited properties.
- The limitation of this approach is that if a property is mapped on the superclass, the column name must be the same on all subclass tables.
- The identity generator strategy is not allowed in union subclass inheritance.
- The primary key seed has to be shared across all unioned subclasses of a hierarchy.
- If your superclass is abstract, map it with abstract=”true”.
- If it is not abstract, an additional table (it defaults to PAYMENT in the example above), is needed to hold instances of the superclass.
Table Per Class Hierarchy |
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/javaskoolDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="pfname">javaskoolMySQLDriver</property>
<property name="connection.password">admin</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping resource="com/javaskool/person.hbm.xml" />
</session-factory>
</hibernate-configuration>
Person.java
package com.javaskool;
public class Person {
private String id;
private String firstName;
private String lastName;
private Integer age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Employee.java
package com.javaskool;
public class Employee extends Person
{
private String projectName;
private String managerName;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getManagerName() {
return managerName;
}
public void setManagerName(String managerName) {
this.managerName = managerName;
}
}
PermanentEmployee.java
package com.javaskool;
public class PermanentEmployee extends Employee
{
private Double salary;
private Double allowance;
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Double getAllowance() {
return allowance;
}
public void setAllowance(Double allowance) {
this.allowance = allowance;
}
}
person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.javaskool">
<class name="Person" table="personTab" discriminator-value="P">
<id name="id"/>
<discriminator column="Emp_Type" type="string"/>
<property name="firstName"></property>
<property name="lastName"></property>
<property name="age"></property>
<subclass name="Employee" discriminator-value="E">
<property name="projectName"></property>
<property name="managerName"></property>
</subclass>
<subclass name="PermanentEmployee" discriminator-value="PE">
<property name="projectName"></property>
<property name="managerName"></property>
<property name="salary"></property>
<property name="allowance"></property>
</subclass>
</class>
</hibernate-mapping>
TestDrive.java
package com.javaskool;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class TestDrive {
public static void main(String[] args) {
Person p1=new Person();
p1.setId("P001");
p1.setFirstName("Tom");
p1.setLastName("Bruce");
p1.setAge(30);
Employee e1=new Employee();
e1.setId("P002");
e1.setFirstName("James");
e1.setLastName("Gosling");
e1.setAge(31);
e1.setProjectName("OnlineChat");
e1.setManagerName("Joseph P");
PermanentEmployee pe1=new PermanentEmployee();
pe1.setId("P003");
pe1.setFirstName("Michael");
pe1.setLastName("Gos");
pe1.setAge(34);
pe1.setProjectName("OnlineCMS");
pe1.setManagerName("Melissa T");
pe1.setSalary(5000.0);
pe1.setAllowance(5009.0);
Configuration confi=new Configuration().configure();
SessionFactory sf=confi.buildSessionFactory();
Session sess=sf.openSession();
Transaction tran=sess.beginTransaction();
sess.save(p1); sess.save(e1); sess.save(pe1);
tran.commit();
}
}
Hibernate Generated Query
Hibernate: insert into personTab (firstName, lastName, age, Emp_Type, id) values (?, ?, ?, 'P', ?)
Hibernate: insert into personTab (firstName, lastName, age, projectName, managerName, Emp_Type, id) values (?, ?, ?, ?, ?, 'E', ?)
Hibernate: insert into personTab (firstName, lastName, age, projectName, managerName, salary, allowance, Emp_Type, id) values (?, ?, ?, ?, ?, ?, ?, 'PE', ?)
Checking Table in MySQL
mysql> show create table personTab;
| personTab | CREATE TABLE `persontab` (
`id` varchar(255) NOT NULL,
`Emp_Type` varchar(255) NOT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`projectName` varchar(255) DEFAULT NULL,
`managerName` varchar(255) DEFAULT NULL,
`salary` double DEFAULT NULL,
`allowance` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> select * from personTab;
+------+----------+-----------+----------+------+-------------+-------------+--------+-------+
| id | Emp_Type | firstName | lastName | age | projectName | managerName |salary|allowance|
+------+----------+-----------+----------+------+-------------+-------------+--------+-------+
| P001 | P | Tom | Bruce | 30 | NULL | NULL |NULL | NULL |
| P002 | E | James | Gosling | 31 | OnlineChat | Joseph P |NULL | NULL |
| P003 | PE | Michael | Gos | 34 | OnlineCMS | Melissa T |5000 | 5009 |
+------+----------+-----------+----------+------+-------------+-------------+--------+-------+
3 rows in set (0.02 sec)
Table Per Subclass |
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/javaskoolDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="pfname">javaskoolMySQLDriver</property>
<property name="connection.password">admin</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping resource="com/javaskool/person.hbm.xml" />
</session-factory>
</hibernate-configuration>
Person.java
package com.javaskool;
public class Person {
private String id;
private String firstName;
private String lastName;
private Integer age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Employee.java
package com.javaskool;
public class Employee extends Person{
private String projectName;
private String managerName;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getManagerName() {
return managerName;
}
public void setManagerName(String managerName) {
this.managerName = managerName;
}
}
PermanentEmployee.java
package com.javaskool;
public class PermanentEmployee extends Employee{
private Double salary;
private Double allowance;
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Double getAllowance() {
return allowance;
}
public void setAllowance(Double allowance) {
this.allowance = allowance;
}
}
person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.javaskool">
<class name="Person" table="personsTab">
<id name="id"/>
<property name="firstName"></property>
<property name="lastName"></property>
<property name="age"></property>
<joined-subclass name="Employee" table="employeesTab">
<key column="id"/>
<property name="projectName"></property>
<property name="managerName"></property>
<joined-subclass name="PermanentEmployee" table="pemployeesTab">
<key column="id"/>
<property name="salary"></property>
<property name="allowance"></property>
</joined-subclass>
</joined-subclass>
</class>
</hibernate-mapping>
TestDrive.java
package com.javaskool;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class TestDrive {
public static void main(String[] args) {
Person p1=new Person();
p1.setId("P001");
p1.setFirstName("Tom");
p1.setLastName("Bruce");
p1.setAge(30);
Employee e1=new Employee();
e1.setId("P002");
e1.setFirstName("James");
e1.setLastName("Gosling");
e1.setAge(31);
e1.setProjectName("Chat System");
e1.setManagerName("Joseph P");
PermanentEmployee pe1=new PermanentEmployee();
pe1.setId("P003");
pe1.setFirstName("Michael");
pe1.setLastName("Gos");
pe1.setAge(34); pe1.setProjectName("CMS");
pe1.setManagerName("Melissa T");
pe1.setSalary(5000.0);
pe1.setAllowance(5009.0);
Configuration confi=new Configuration().configure();
SessionFactory sf=confi.buildSessionFactory();
Session sess=sf.openSession();
Transaction tran=sess.beginTransaction();
sess.save(p1); sess.save(e1); sess.save(pe1);
tran.commit();
}
}
Hibernate Generated Query
Hibernate: insert into personsTab (firstName, lastName, age, id) values (?, ?, ?, ?)
Hibernate: insert into personsTab (firstName, lastName, age, id) values (?, ?, ?, ?)
Hibernate: insert into employeesTab (projectName, managerName, id) values (?, ?, ?)
Hibernate: insert into personsTab (firstName, lastName, age, id) values (?, ?, ?, ?)
Hibernate: insert into employeesTab (projectName, managerName, id) values (?, ?, ?)
Hibernate: insert into pemployeesTab (salary, allowance, id) values (?, ?, ?)
Checking Table in MySQL
mysql> show create table personsTab;
| personsTab | CREATE TABLE `personstab` (
`id` varchar(255) NOT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> show create table employeesTab;
| employeesTab | CREATE TABLE `employeestab` (
`id` varchar(255) NOT NULL,
`projectName` varchar(255) DEFAULT NULL,
`managerName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK88244C61A8115279` (`id`),
CONSTRAINT `FK88244C61A8115279` FOREIGN KEY (`id`) REFERENCES `personstab1` (`
id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> show create table pemployeesTab;
| pemployeesTab | CREATE TABLE `pemployeestab` (
`id` varchar(255) NOT NULL,
`salary` double DEFAULT NULL,
`allowance` double DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK592C81F1158E3F92` (`id`),
CONSTRAINT `FK592C81F1158E3F92` FOREIGN KEY (`id`) REFERENCES `employeestab1`
(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> select * from personsTab;
+------+-----------+----------+------+
| id | firstName | lastName | age |
+------+-----------+----------+------+
| P001 | Tom | Bruce | 30 |
| P002 | James | Gosling | 31 |
| P003 | Michael | Gos | 34 |
+------+-----------+----------+------+
3 rows in set (0.00 sec)
mysql> select * from employeesTab;
+------+-------------+-------------+
| id | projectName | managerName |
+------+-------------+-------------+
| P002 | Chat System | Joseph P |
| P003 | CMS | Melissa T |
+------+-------------+-------------+
2 rows in set (0.00 sec)
mysql> select * from pemployeesTab;
+------+--------+-----------+
| id | salary | allowance |
+------+--------+-----------+
| P003 | 5000 | 5009 |
+------+--------+-----------+
1 row in set (0.00 sec)
mysql>
Table Per Concrete Class |
hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">jdbc:mysql://localhost:3306/javaskoolDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="pfname">javaskoolMySQLDriver</property>
<property name="connection.password">admin</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<mapping resource="com/javaskool/person.hbm.xml" />
</session-factory>
</hibernate-configuration>
Person.java
package com.javaskool;
public class Person {
private String id;
private String firstName;
private String lastName;
private Integer age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Employee.java
package com.javaskool;
public class Employee extends Person{
private String projectName;
private String managerName;
public String getProjectName() {
return projectName;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public String getManagerName() {
return managerName;
}
public void setManagerName(String managerName) {
this.managerName = managerName;
}
}
PermanentEmployee.java
package com.javaskool;
public class PermanentEmployee extends Employee{
private Double salary;
private Double allowance;
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Double getAllowance() {
return allowance;
}
public void setAllowance(Double allowance) {
this.allowance = allowance;
}
}
person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.javaskool">
<class name="Person" table="personsTab2">
<id name="id"/>
<property name="firstName"></property>
<property name="lastName"></property>
<property name="age"></property>
</class>
<class name="Employee" table="employeesTab2">
<id name="id"/>
<property name="firstName"></property>
<property name="lastName"></property>
<property name="age"></property>
<property name="projectName"></property>
<property name="managerName"></property>
</class>
<class name="PermanentEmployee" table="pemployeesTab2">
<id name="id"/>
<property name="firstName"></property>
<property name="lastName"></property>
<property name="age"></property>
<property name="projectName"></property>
<property name="managerName"></property>
<property name="salary"></property>
<property name="allowance"></property>
</class>
</hibernate-mapping>
TestDrive.java
package com.javaskool;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class TestDrive {
public static void main(String[] args) {
Person p1=new Person();
p1.setId("P0001");
p1.setFirstName("Tom");
p1.setLastName("Charly");
p1.setAge(30);
Employee e1=new Employee();
e1.setId("P0002");
e1.setFirstName("Megna");
e1.setLastName("Lanning");
e1.setAge(31);
e1.setProjectName("OnlineChat");
e1.setManagerName("Lisa sthatel");
PermanentEmployee pe1=new PermanentEmployee();
pe1.setId("P0003");
pe1.setFirstName("Michael");
pe1.setLastName("Josheph");
pe1.setAge(34);
pe1.setProjectName("CMS");
pe1.setManagerName("Melissa T");
pe1.setSalary(5000.0);
pe1.setAllowance(5009.0);
Configuration confi=new Configuration().configure();
SessionFactory sf=confi.buildSessionFactory();
Session sess=sf.openSession();
Transaction tran=sess.beginTransaction();
sess.save(p1); sess.save(e1); sess.save(pe1);
tran.commit();
}}
Hibernate Generated Query
Hibernate: insert into personsTab2 (firstName, lastName, age, id) values (?, ?, ?, ?)
Hibernate: insert into employeesTab2 (firstName, lastName, age, projectName, managerName, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into pemployeesTab2 (firstName, lastName, age, projectName, managerName, salary, allowance, id) values (?, ?, ?, ?, ?, ?, ?, ?)
Checking Table in MySQL
mysql> show create table personsTab2;
| personsTab2 | CREATE TABLE `personstab2` (
`id` varchar(255) NOT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> show create table employeesTab2;
| employeesTab2 | CREATE TABLE `employeestab2` (
`id` varchar(255) NOT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`projectName` varchar(255) DEFAULT NULL,
`managerName` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> show create table pemployeesTab2;
| pemployeesTab2 | CREATE TABLE `pemployeestab2` (
`id` varchar(255) NOT NULL,
`firstName` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`projectName` varchar(255) DEFAULT NULL,
`managerName` varchar(255) DEFAULT NULL,
`salary` double DEFAULT NULL,
`allowance` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
mysql> select * from personsTab2;
+-------+-----------+----------+------+
| id | firstName | lastName | age |
+-------+-----------+----------+------+
| P0001 | Tom | Charly | 30 |
+-------+-----------+----------+------+
1 row in set (0.00 sec)
mysql> select * from employeesTab2;
+-------+-----------+----------+------+-------------+--------------+
| id | firstName | lastName | age | projectName | managerName |
+-------+-----------+----------+------+-------------+--------------+
| P0002 | Megna | Lanning | 31 | OnlineChat | Lisa sthatel |
+-------+-----------+----------+------+-------------+--------------+
1 row in set (0.00 sec)
mysql> select * from pemployeesTab2;
+-------+-----------+----------+------+-------------+-------------+--------+-----------+
| id | firstName | lastName | age | projectName | managerName | salary | allowance |
+-------+-----------+----------+------+-------------+-------------+--------+-----------+
| P0003 | Michael | Josheph | 34 | CMS | Melissa T | 5000 | 5009 |
+-------+-----------+----------+------+-------------+-------------+--------+-----------+
1 row in set (0.02 sec)
Download Examples |
Recent Comments