alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (inheritance_mapping.xml)

This example Hibernate source code file (inheritance_mapping.xml) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

cashpayment, cdata, chequepayment, credit_payment, creditcardpayment, hibernate, payment, payment, payment_id, payment_id, the, the, xml, xml

The Hibernate inheritance_mapping.xml source code

<?xml version='1.0' encoding="UTF-8"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
  ~ indicated by the @author tags or express copyright attribution
  ~ statements applied by the authors.  All third-party contributions are
  ~ distributed under license by Red Hat Middleware LLC.
  ~
  ~ This copyrighted material is made available to anyone wishing to use, modify,
  ~ copy, or redistribute it subject to the terms and conditions of the GNU
  ~ Lesser General Public License, as published by the Free Software Foundation.
  ~
  ~ This program is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
%BOOK_ENTITIES;

]>

<chapter id="inheritance">
    <title>Inheritance mapping

    <section id="inheritance-strategies" revision="3">
        <title>The three strategies

        <para>
            Hibernate supports the three basic inheritance mapping strategies:
        </para>

        <itemizedlist>
        <listitem>
        <para>
            table per class hierarchy
        </para>
        </listitem>
        <listitem>
        <para>
            table per subclass
        </para>
        </listitem>
        <listitem>
        <para>
            table per concrete class
        </para>
        </listitem>
        </itemizedlist>
        
        <para>
            In addition, Hibernate supports a fourth, slightly different kind of 
            polymorphism:
        </para>

        <itemizedlist>
        <listitem>
        <para>
            implicit polymorphism
        </para>
        </listitem>
        </itemizedlist>
        
        <para>
            It is possible to use different mapping strategies for different
            branches of the same inheritance hierarchy. You can then make use of implicit
            polymorphism to achieve polymorphism across the whole hierarchy. However, 
            Hibernate does not support mixing <literal><subclass>,
            <literal><joined-subclass> and 
            <literal><union-subclass> mappings under the same root
            <literal><class> element. It is possible to mix together
            the table per hierarchy and table per subclass strategies under the
            the same <literal><class> element, by combining the 
            <literal><subclass> and <join>
            elements (see below for an example).
        </para>

        <para>
             It is possible to define <literal>subclass, union-subclass,
             and <literal>joined-subclass mappings in separate mapping documents directly beneath
             <literal>hibernate-mapping. This allows you to extend a class hierarchy by adding
             a new mapping file. You must specify an <literal>extends attribute in the subclass mapping,
             naming a previously mapped superclass. Previously this feature made the ordering of the mapping
             documents important. Since Hibernate3, the ordering of mapping files is irrelevant when using the
             extends keyword. The ordering inside a single mapping file still needs to be defined as superclasses
             before subclasses.
         </para>

         <programlisting role="XML">


        <section id="inheritance-tableperclass" >
        <title>Table per class hierarchy

        <para>
            Suppose we have an interface <literal>Payment with the implementors
            <literal>CreditCardPayment, CashPayment,
            and <literal>ChequePayment. The table per hierarchy mapping would
            display in the following way:
        </para>

        <programlisting role="XML">
    <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>]]>

        <para>
            Exactly one table is required. There is a limitation of this mapping 
            strategy: columns declared by the subclasses, such as <literal>CCTYPE, 
            cannot have <literal>NOT NULL constraints.
        </para>
        
        </section>

        <section id="inheritance-tablepersubclass">
        <title>Table per subclass

        <para>
            A table per subclass mapping looks like this:
        </para>

        <programlisting role="XML">
    <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>]]>

        <para>
            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.
        </para>

        </section>

        <section id="inheritance-tablepersubclass-discriminator" revision="2">
        <title>Table per subclass: using a discriminator

        <para>
            Hibernate's implementation of table per subclass
            does not require a discriminator column. Other object/relational mappers use a
            different implementation of table per subclass that requires a type
            discriminator column in the superclass table. The approach taken by
            Hibernate is much more difficult to implement, but arguably more
            correct from a relational point of view. If you want to use
            a discriminator column with the table per subclass strategy, you
            can combine the use of <literal><subclass> and 
            <literal><join>, as follows:
        </para>

        <programlisting role="XML">
    <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">
        <join table="CREDIT_PAYMENT">
            <key column="PAYMENT_ID"/>
            <property name="creditCardType" column="CCTYPE"/>
            ...
        </join>
    </subclass>
    <subclass name="CashPayment" discriminator-value="CASH">
        <join table="CASH_PAYMENT">
            <key column="PAYMENT_ID"/>
            ...
        </join>
    </subclass>
    <subclass name="ChequePayment" discriminator-value="CHEQUE">
        <join table="CHEQUE_PAYMENT" fetch="select">
            <key column="PAYMENT_ID"/>
            ...
        </join>
    </subclass>
</class>]]>

        <para>
            The optional <literal>fetch="select" declaration tells Hibernate 
            not to fetch the <literal>ChequePayment subclass data using an
            outer join when querying the superclass.
        </para>

        </section>

        <section id="inheritance-mixing-tableperclass-tablepersubclass">
        <title>Mixing table per class hierarchy with table per subclass

        <para>
            You can even mix the table per hierarchy and table per subclass strategies
            using the following approach:
        </para>

        <programlisting role="XML">
    <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">
        <join table="CREDIT_PAYMENT">
            <property name="creditCardType" column="CCTYPE"/>
            ...
        </join>
    </subclass>
    <subclass name="CashPayment" discriminator-value="CASH">
        ...
    </subclass>
    <subclass name="ChequePayment" discriminator-value="CHEQUE">
        ...
    </subclass>
</class>]]>

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

        <programlisting role="XML">]]>
    
        </section>

        <section id="inheritance-tableperconcrete" revision="2">
        <title>Table per concrete class

        <para>
            There are two ways we can map the table per concrete class
            strategy. First, you can use <literal><union-subclass>.
        </para>

        <programlisting role="XML">
    <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>]]>

        <para>
            Three tables are involved for the subclasses. Each table defines columns for
            all properties of the class, including inherited properties.
        </para>
        
        <para>
            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.
	
        </para>

        <para>
            If your superclass is abstract, map it with <literal>abstract="true".
            If it is not abstract, an additional table (it defaults to
            <literal>PAYMENT in the example above), is needed to hold instances
            of the superclass.
        </para>

        </section>

        <section id="inheritance-tableperconcreate-polymorphism">
        <title>Table per concrete class using implicit polymorphism

        <para>
            An alternative approach is to make use of implicit polymorphism:
        </para>

        <programlisting role="XML">
    <id name="id" type="long" column="CREDIT_PAYMENT_ID">
        <generator class="native"/>
    </id>
    <property name="amount" column="CREDIT_AMOUNT"/>
    ...
</class>

<class name="CashPayment" table="CASH_PAYMENT">
    <id name="id" type="long" column="CASH_PAYMENT_ID">
        <generator class="native"/>
    </id>
    <property name="amount" column="CASH_AMOUNT"/>
    ...
</class>

<class name="ChequePayment" table="CHEQUE_PAYMENT">
    <id name="id" type="long" column="CHEQUE_PAYMENT_ID">
        <generator class="native"/>
    </id>
    <property name="amount" column="CHEQUE_AMOUNT"/>
    ...
</class>]]>
           
        <para>
            Notice that the <literal>Payment interface 
            is not mentioned explicitly. Also notice that properties of <literal>Payment are 
            mapped in each of the subclasses. If you want to avoid duplication, consider
            using XML entities
            (for example, <literal>[ <!ENTITY allproperties SYSTEM "allproperties.xml"> ]
            in the <literal>DOCTYPE declaration and 
            <literal>&allproperties; in the mapping).
        </para>
        
        <para>
            The disadvantage of this approach is that Hibernate does not generate SQL
            <literal>UNIONs when performing polymorphic queries.
        </para>

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

        <programlisting role="XML">
    <meta-value value="CREDIT" class="CreditCardPayment"/>
    <meta-value value="CASH" class="CashPayment"/>
    <meta-value value="CHEQUE" class="ChequePayment"/>
    <column name="PAYMENT_CLASS"/>
    <column name="PAYMENT_ID"/>
</any>]]>
           
        </section>

        <section id="inheritance-mixingpolymorphism">
        <title>Mixing implicit polymorphism with other inheritance mappings

        <para>
            Since the subclasses 
            are each mapped in their own <literal><class> element, and since
            <literal>Payment is just an interface), each of the subclasses could 
            easily be part of another inheritance hierarchy. You can still use polymorphic
            queries against the <literal>Payment interface.
       </para>

        <programlisting role="XML">
    <id name="id" type="long" column="CREDIT_PAYMENT_ID">
        <generator class="native"/>
    </id>
    <discriminator column="CREDIT_CARD" type="string"/>
    <property name="amount" column="CREDIT_AMOUNT"/>
    ...
    <subclass name="MasterCardPayment" discriminator-value="MDC"/>
    <subclass name="VisaPayment" discriminator-value="VISA"/>
</class>

<class name="NonelectronicTransaction" table="NONELECTRONIC_TXN">
    <id name="id" type="long" column="TXN_ID">
        <generator class="native"/>
    </id>
    ...
    <joined-subclass name="CashPayment" table="CASH_PAYMENT">
        <key column="PAYMENT_ID"/>
        <property name="amount" column="CASH_AMOUNT"/>
        ...
    </joined-subclass>
    <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
        <key column="PAYMENT_ID"/>
        <property name="amount" column="CHEQUE_AMOUNT"/>
        ...
    </joined-subclass>
</class>]]>

        <para>
            Once again, <literal>Payment is not mentioned explicitly. If we
            execute a query against the <literal>Payment interface, for
            example <literal>from Payment, Hibernate
            automatically returns instances of <literal>CreditCardPayment
            (and its subclasses, since they also implement <literal>Payment),
            <literal>CashPayment and ChequePayment, but
            not instances of <literal>NonelectronicTransaction.
        </para>
        
        </section>

    </section>

    <section id="inheritance-limitations">
        <title>Limitations

        <para>
            There are limitations to the "implicit polymorphism" approach to
            the table per concrete-class mapping strategy. There are somewhat less
            restrictive limitations to <literal><union-subclass>
            mappings.
        </para>

        <para>
            The following table shows the limitations of table per concrete-class
            mappings, and of implicit polymorphism, in Hibernate.
        </para>
            
        <table frame="topbot">
            <title>Features of inheritance mappings
            <tgroup cols='9' align='left' colsep='1' rowsep='1'>
            <colspec colname='c1' colwidth="1*"/>
            <colspec colname='c2' colwidth="1*"/>
            <colspec colname='c3' colwidth="1*"/>
            <colspec colname='c4' colwidth="1*"/>
            <colspec colname='c5' colwidth="1*"/>
            <colspec colname='c6' colwidth="1*"/>
            <colspec colname='c7' colwidth="1*"/>
            <colspec colname='c8' colwidth="1*"/>
            <colspec colname='c9' colwidth="1*"/>
            <thead>
            <row>
              <entry>Inheritance strategy
              <entry>Polymorphic many-to-one
              <entry>Polymorphic one-to-one
              <entry>Polymorphic one-to-many
              <entry>Polymorphic many-to-many
              <entry>Polymorphic load()/get()
              <entry>Polymorphic queries
              <entry>Polymorphic joins
              <entry>Outer join fetching
            </row>
            </thead>
            <tbody>
            <row>
                <entry>table per class-hierarchy
                <entry><many-to-one>
                <entry><one-to-one>
                <entry><one-to-many>
                <entry><many-to-many>
                <entry>s.get(Payment.class, id)
                <entry>from Payment p
                <entry>from Order o join o.payment p
                <entry>supported
            </row>
            <row>
                <entry>table per subclass
                <entry><many-to-one>
                <entry><one-to-one>
                <entry><one-to-many>
                <entry><many-to-many>
                <entry>s.get(Payment.class, id)
                <entry>from Payment p
                <entry>from Order o join o.payment p
                <entry>supported
            </row>
            <row>
                <entry>table per concrete-class (union-subclass)
                <entry><many-to-one>
                <entry><one-to-one>
                <entry><one-to-many> (for inverse="true" only)
                <entry><many-to-many>
                <entry>s.get(Payment.class, id)
                <entry>from Payment p
                <entry>from Order o join o.payment p
                <entry>supported
            </row>
            <row>
                <entry>table per concrete class (implicit polymorphism)
                <entry><any>
                <entry>not supported
                <entry>not supported
                <entry><many-to-any>
                <entry>s.createCriteria(Payment.class).add( Restrictions.idEq(id) ).uniqueResult()
                <entry>from Payment p
                <entry>not supported
                <entry>not supported
            </row>
            </tbody>
            </tgroup>
        </table>

    </section>

</chapter>

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate inheritance_mapping.xml source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.