Hibernate Inheritance Mapping

Hibernate provide the three basic inheritance mapping strategies. They are

  1. Table per class hierarchy
  2. Table per subclass
  3. Table per concrete class
  4. Mixing inheritance

Table per class hierarchy

Here the table has one row for each field in the entire class hierarchy. You will have plenty of potential null values and you have a discriminator column to contain type information. The table per hierarchy mapping is used as an interface Payment with the implementers CreditCardPayment, CashPayment and ChequePayment.

Table per class hierarchy
Table per class hierarchy

Eg: –

 <class table="PAYMENT">
<id column="PAYMENT_ID">
<generator/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property column="AMOUNT"/>
...
<subclass discriminator-value="CREDIT">
<property column="CCTYPE"/>
...
</subclass>
<subclass discriminator-value="CASH">
<property column="CPTYPE"/>
...
</subclass>
</class>

Only one table is required for this strategy. The limitation of this strategy is the columns declared by the subclasses, such as CCTYPE cannot have NOT NULL constrains.

Advantages:-

Very efficient

Disadvantages:-

  1. Data integrity: – At the time of declaration we may declare the subclass columns as nullable. This sometimes leads to data integrity problem.
  2. Violating third normal form.

Table per subclass

The table type subclass works in two different ways.

1)      Table per subclass without discriminator

Here we are using four tables. The three subclass tables have primary key associations to the superclass table so the relational model is actually a one to one association.

Eg: –

<class table="PAYMENT">
<id column="PAYMENT_ID">
<generator/>
</id>
<property column="AMOUNT"/>
...
<joined-subclass table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
<property column="CCTYPE"/>
...
</joined-subclass>
<joined-subclass table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
<joined-subclass table="CHEQUE_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
</class>

 

Table per subclass with discriminator

Here we are using the discriminator column in the superclass table. If you want to use a discriminator column with the table per subclass type, you can combine the use of <subclass> and <join>.

Eg: –

 <class table="PAYMENT">
<id column="PAYMENT_ID">
<generator class="native"/>
</id>
<discriminator column="PAYMENT_TYPE"/>
<property column="AMOUNT"/>
...
<subclass name="CreditCardPayment" discriminator-value="CREDIT">
<join table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
<property column="CCTYPE"/>
...
</join>
</subclass>
<subclass discriminator-value="CASH">
<join table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</join>
</subclass>
<subclass discriminator-value="CHEQUE">
<join table="CHEQUE_PAYMENT" fetch="select">
<key column="PAYMENT_ID"/>
...
</join>
</subclass>
</class>

 

The optional fetch=”select” declaration tells Hibernate not to fetch the ChequePayment subclass data using an outer join when querying the superclass.

Table per concrete class

Table per concrete class uses two methods. They are,

1)      Table per concrete class without using implicit polymorphism

In this method we are using <union-subclass>. Three tables are involved for the subclasses.

Eg: –

<class name="Payment">
<id column="PAYMENT_ID">
<generator/>
</id>
<property column="AMOUNT"/>
...
<union-subclass table="CREDIT_PAYMENT">
<property column="CCTYPE"/>
...
</union-subclass>
<union-subclass table="CASH_PAYMENT">
...
</union-subclass>
<union-subclass table="CHEQUE_PAYMENT">
...
</union-subclass>
</class>

2)      Table per concrete class using implicit polymorphism

Notice that the Payment interface is not mentioned explicitly. Also notice that properties of Payment are mapped in each of the subclasses. If you want to avoid duplication, consider using XML entities (for example, [<! ENTITY allproperties SYSTEM “allproperties.xml”>] in the DOCTYPE declaration and & allproperties; in the mapping).

Eg: –

<class name="CreditCardPayment" table="CREDIT_PAYMENT">
<id column="CREDIT_PAYMENT_ID">
<generator/>
</id>
<property column="CREDIT_AMOUNT"/>
...
</class>
<class table="CASH_PAYMENT">
<id column="CASH_PAYMENT_ID">
<generator/>
</id>
<property column="CASH_AMOUNT"/>
...
</class>
<class table="CHEQUE_PAYMENT">
<id column="CHEQUE_PAYMENT_ID">
<generator/>
</id>
<property column="CHEQUE_AMOUNT"/>
...
</class>

For this mapping strategy, a polymorphic association to Payment is usually mapped using <any>.

Eg: –

<any meta-type="string" id-type="long">
<meta-value value="CREDIT" class="CreditCardPayment"/>
<meta-value value="CASH" class="CashPayment"/>
<meta-value value="CHEQUE"/>
<column name="PAYMENT_CLASS"/>
<column/>
</any>

Advantages:-

  1. Simple
  2. Efficient

Disadvantages:-

  1. When we associate other entity with the super class, we will face problems.
  2. If you have a query against the super class, you will have to query several times for each sub-class tables.
  3. A change of super class properties will affect in each sub class tables.

Mixing inheritance

Mixing inheritance approach is done in two ways. They are,

1)      Mixing table per class hierarchy with table per subclass

The following example shows how to handle mixing table per class hierarchy with table per subclass type inheritance.

Eg:-

<class table="PAYMENT">
<id column="PAYMENT_ID">
<generator/>
</id>
<discriminator column="PAYMENT_TYPE" type="string"/>
<property column="AMOUNT"/>
...
<subclass discriminator-value="CREDIT">
<join table="CREDIT_PAYMENT">
<property name="creditCardType" column="CCTYPE"/>
...
</join>
</subclass>
<subclass discriminator-value="CASH">
...
</subclass>
<subclass name="ChequePayment" discriminator-value="CHEQUE">
...
</subclass>
</class>

For any of these mapping strategies, a polymorphic association to the root Payment class is mapped using <many-to-one>.

<many-to-one column=”PAYMENT_ID”/>

2)      Mixing implicit polymorphism with other inheritance mappings

Since the subclasses are each mapped in their own <class> element and since the payment is only one interface, each of the subclasses could easily be part of another inheritance hierarchy. You can still use polymorphic queries against the Payment interface.

Eg:-
<class table="CREDIT_PAYMENT">
<id column="CREDIT_PAYMENT_ID">
<generator/>
</id>
<discriminator column="CREDIT_CARD" type="string"/>
<property column="CREDIT_AMOUNT"/>
...
<subclass discriminator-value="MDC"/>
<subclass discriminator-value="VISA"/>
</class>

<class name="NonelectronicTransaction" table="NONELECTRONIC_TXN">
<id column="TXN_ID">
<generator/>
</id>
...
<joined-subclass table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
<property column="CASH_AMOUNT"/>
...
</joined-subclass>
<joined-subclass table="CHEQUE_PAYMENT">
<key column="PAYMENT_ID"/>
<property column="CHEQUE_AMOUNT"/>
...
</joined-subclass>
</class>

Features of Inheritance Mapping

 

Inheritance Mapping
Inheritance Mapping