Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Table Per Subclass Example using XML File

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.

1. Setting Up:

Make sure you've set up a Hibernate project with the necessary configurations and dependencies.

2. Define the Entity Classes:

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...
}

3. XML Mapping:

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.
  • The 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).

4. Persistence:

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.

5. Fetching:

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.

6. Benefits & Drawbacks:

Benefits:

  • More normalized database schema.
  • No wasted space, as subclass tables only contain columns specific to them.

Drawbacks:

  • Fetching operations can be slower due to the required JOIN operations between superclass and subclass tables.
  • Insert or update operations involve multiple tables.

Conclusion:

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.

  1. Hibernate table per subclass XML mapping example:

    • Table per subclass XML mapping in Hibernate involves configuring each subclass with its own mapping file.
    • Use <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>
    
  2. Configuring table per subclass inheritance in Hibernate using XML:

    • Configure table per subclass inheritance in Hibernate XML by using <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>
    
  3. Mapping subclasses with Hibernate XML mapping:

    • Map subclasses using <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>
    
  4. Table per subclass vs table per hierarchy in Hibernate XML:

    • In Hibernate XML, table per subclass involves using separate <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>
    
  5. Inheritance strategies with XML mapping in Hibernate:

    • In Hibernate XML mapping, inheritance strategies are defined using <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>
    
  6. Hibernate XML mapping for @Inheritance annotation in table per subclass:

    • The <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>
    
  7. Handling associations in table per subclass mapping with XML:

    • Handle associations in table per subclass mapping with XML by defining relationships in the XML mapping files.
    <!-- 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>
    
  8. HQL queries for table per subclass inheritance in Hibernate XML:

    • Use HQL (Hibernate Query Language) for queries specific to the table per subclass strategy 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.