Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Table Per Hierarchy using XML File

Using the "Table Per Hierarchy" strategy with Hibernate means storing all entities of an inheritance hierarchy in a single table, differentiated by a discriminator column. This tutorial will guide you on how to map this strategy using XML configuration.

1. Setting Up:

Ensure you have a Hibernate project ready with the necessary dependencies and configuration files.

2. Define the Entity Classes:

Base Class (Vehicle):

This class will be our parent class.

public abstract class Vehicle {

    private Long id;
    private String manufacturer;

    // Getters, setters, constructors...
}

Concrete Subclasses (Car and Bike):

public class Car extends Vehicle {

    private int numberOfSeats;

    // Getters, setters, constructors...
}

public class Bike extends Vehicle {

    private int saddleHeight;

    // Getters, setters, constructors...
}

3. XML Mapping:

Vehicle.hbm.xml:

<hibernate-mapping>
    <class name="Vehicle" table="VEHICLE" discriminator-value="none" abstract="true">
        <id name="id" column="ID">
            <generator class="native"/>
        </id>
        <discriminator column="VEHICLE_TYPE" type="string"/>
        <property name="manufacturer" column="MANUFACTURER"/>
        
        <!-- Subclass mappings -->
        <subclass name="Car" discriminator-value="Car">
            <property name="numberOfSeats" column="NUMBER_OF_SEATS"/>
        </subclass>
        <subclass name="Bike" discriminator-value="Bike">
            <property name="saddleHeight" column="SADDLE_HEIGHT"/>
        </subclass>
    </class>
</hibernate-mapping>

In the above XML:

  • discriminator tag is used to specify the discriminator column.
  • subclass tag is used to define the properties and discriminator values of each subclass.

Ensure that this XML file is appropriately registered in your Hibernate configuration file (hibernate.cfg.xml).

4. Persistence:

When you create and save an instance of Car:

Car car = new Car();
car.setManufacturer("Toyota");
car.setNumberOfSeats(4);

session.save(car);

Hibernate will generate an insert statement for the VEHICLE table with a VEHICLE_TYPE of "Car".

5. Fetching:

When you fetch an entity, Hibernate will look at the discriminator column to determine which entity type to instantiate.

Vehicle retrievedVehicle = session.get(Vehicle.class, vehicleId);

If the VEHICLE_TYPE for the given ID is "Car", retrievedVehicle will actually be an instance of Car.

6. Benefits & Drawbacks:

Benefits:

  • Single table for the entire hierarchy simplifies the schema.
  • Easier data retrieval because only one table is involved.

Drawbacks:

  • The table can become wide with many nullable columns if subclasses have varied properties.
  • Schema changes may become necessary if the hierarchy changes.

Conclusion:

"Table Per Hierarchy" is a compact way of mapping an inheritance hierarchy to a relational database when using Hibernate's XML configuration. While it's efficient for querying, care should be taken when designing the hierarchy to avoid a table with many nullable columns. Always choose the inheritance strategy based on your application's requirements.

  1. Hibernate table per hierarchy XML mapping example:

    • Table per hierarchy XML mapping in Hibernate involves configuring the entire hierarchy in a single XML mapping file.
    • Use <class> elements for each class and <discriminator> for the discriminator column.
    <!-- Animal.hbm.xml -->
    <class name="com.example.Animal" table="animal">
        <id name="id" type="long">
            <generator class="increment"/>
        </id>
        <discriminator column="animal_type" type="string"/>
        <!-- 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 hierarchy inheritance in Hibernate using XML:

    • Configure table per hierarchy 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>
        <discriminator column="animal_type" type="string"/>
        <!-- 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 hierarchical classes with Hibernate XML mapping:

    • Map hierarchical classes 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>
        <discriminator column="animal_type" type="string"/>
        <!-- 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 hierarchy vs table per concrete class in Hibernate XML:

    • In Hibernate XML, table per hierarchy involves using a single <class> element for the entire hierarchy, while table per concrete class uses separate <class> elements for each concrete class.
    <!-- Table per hierarchy -->
    <class name="com.example.Animal" table="animal">
        <!-- Common fields and mappings -->
    </class>
    
    <!-- Table per concrete class -->
    <class name="com.example.Cat" table="cat">
        <!-- Cat-specific fields and mappings -->
    </class>
    
    <!-- Table per concrete class -->
    <class name="com.example.Dog" table="dog">
        <!-- Dog-specific fields and mappings -->
    </class>
    
  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 hierarchy:

    • The <class> and <subclass> elements in Hibernate XML correspond to the @Inheritance(strategy = InheritanceType.SINGLE_TABLE) annotation in table per hierarchy.
    <!-- Animal.hbm.xml -->
    <class name="com.example.Animal" table="animal">
        <discriminator column="animal_type" type="string"/>
        <!-- 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 hierarchy mapping with XML:

    • Handle associations in table per hierarchy mapping with XML by defining relationships in the XML mapping files.
    <!-- Animal.hbm.xml -->
    <class name="com.example.Animal" table="animal">
        <discriminator column="animal_type" type="string"/>
        <!-- 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 hierarchy inheritance in Hibernate XML:

    • Use HQL (Hibernate Query Language) for queries specific to the table per hierarchy strategy in Hibernate XML.
    String hql = "FROM Animal WHERE color = :color";
    Query query = session.createQuery(hql);
    query.setParameter("color", "black");
    List<Animal> blackAnimals = query.list();
    

    Replace this code with the relevant XML configuration.