Hibernate Tutorial
Core Hibernate
Hibernate Mapping
Hibernate Annotations
Hibernate with Spring Framework
Hibernate with Database
Hibernate Log4j
Inheritance Mapping
The "Table Per Subclass" strategy is a Hibernate inheritance mapping approach where each class (including subclasses) gets its own table, but the subclass tables only contain columns for the attributes introduced by the subclass. This strategy uses "joined" tables which means that subclass tables are joined to the superclass table based on primary key.
In this tutorial, we'll see how to map inheritance using the "Table Per Subclass" strategy with XML configuration.
Make sure you've set up a Hibernate project with the necessary configurations and dependencies.
Base Class (Person):
public class Person { private Long id; private String name; // Getters, setters, constructors... }
Subclasses (Employee and Customer):
public class Employee extends Person { private double salary; // Getters, setters, constructors... } public class Customer extends Person { private String purchasedProduct; // Getters, setters, constructors... }
Person.hbm.xml:
<hibernate-mapping> <class name="Person" table="PERSON"> <id name="id" column="ID"> <generator class="native"/> </id> <property name="name" column="NAME"/> <!-- Subclass mappings --> <joined-subclass name="Employee" table="EMPLOYEE"> <key column="PERSON_ID"/> <property name="salary" column="SALARY"/> </joined-subclass> <joined-subclass name="Customer" table="CUSTOMER"> <key column="PERSON_ID"/> <property name="purchasedProduct" column="PURCHASED_PRODUCT"/> </joined-subclass> </class> </hibernate-mapping>
In the mapping:
joined-subclass
is used to specify that the subclass is stored in its table and is joined to the superclass table.key
tag inside joined-subclass
tells Hibernate which column is used to join the subclass table to the superclass table.Ensure this XML is correctly registered in your Hibernate configuration file (hibernate.cfg.xml
).
When you create and save an instance of Employee
:
Employee emp = new Employee(); emp.setName("John Doe"); emp.setSalary(50000); session.save(emp);
Hibernate will insert data into both PERSON
and EMPLOYEE
tables.
Fetching works seamlessly:
Employee retrievedEmployee = session.get(Employee.class, empId);
Hibernate will generate a SQL JOIN operation between PERSON
and EMPLOYEE
tables to fetch the complete Employee
object.
Benefits:
Drawbacks:
The "Table Per Subclass" strategy using XML configurations in Hibernate offers a normalized approach to map inheritance in a relational database. It's suitable when you want to avoid single wide tables with many nullable columns (as in Table Per Hierarchy). Always choose your inheritance strategy based on the specific needs and performance considerations of your application.
Hibernate table per subclass XML mapping example:
<class>
elements for each class and <subclass>
for inheritance.<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <id name="id" type="long"> <generator class="increment"/> </id> <!-- Common fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Dog.hbm.xml --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Configuring table per subclass inheritance in Hibernate using XML:
<class>
and <subclass>
elements in the same mapping file.<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <id name="id" type="long"> <generator class="increment"/> </id> <!-- Common fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Dog.hbm.xml --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Mapping subclasses with Hibernate XML mapping:
<class>
elements for the superclass and <subclass>
elements for each subclass.<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <id name="id" type="long"> <generator class="increment"/> </id> <!-- Common fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Dog.hbm.xml --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Table per subclass vs table per hierarchy in Hibernate XML:
<class>
and <subclass>
elements for each subclass, while table per hierarchy uses a single <class>
element for the entire hierarchy.<!-- Table per subclass --> <class name="com.example.Animal" table="animal"> <!-- Common fields and mappings --> </class>
<!-- Table per subclass --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Table per subclass --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Inheritance strategies with XML mapping in Hibernate:
<subclass>
, <joined-subclass>
, or <union-subclass>
elements.<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <!-- Common fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Dog.hbm.xml --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Hibernate XML mapping for @Inheritance annotation in table per subclass:
<class>
and <subclass>
elements in Hibernate XML correspond to the @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
annotation in table per subclass.<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <!-- Common fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> </subclass>
<!-- Dog.hbm.xml --> <subclass name="com.example.Dog" extends="com.example.Animal" discriminator-value="DOG"> <!-- Dog-specific fields and mappings --> </subclass>
Handling associations in table per subclass mapping with XML:
<!-- Animal.hbm.xml --> <class name="com.example.Animal" table="animal"> <!-- Common fields and mappings --> </class>
<!-- Person.hbm.xml --> <class name="com.example.Person" table="person"> <!-- Person-specific fields and mappings --> </class>
<!-- Cat.hbm.xml --> <subclass name="com.example.Cat" extends="com.example.Animal" discriminator-value="CAT"> <!-- Cat-specific fields and mappings --> <many-to-one name="owner" class="com.example.Person" column="owner_id"/> </subclass>
HQL queries for table per subclass inheritance in Hibernate XML:
String hql = "FROM Cat WHERE color = :color"; Query query = session.createQuery(hql); query.setParameter("color", "black"); List<Cat> blackCats = query.list();
Replace this code with the relevant XML configuration.