Hibernate.orgCommunity Documentation

Capítulo 9. Inheritance mapping

9.1. The three strategies
9.1.1. Tabla por jerarquía de clases
9.1.2. Tabla por subclase
9.1.3. Table per subclass: using a discriminator
9.1.4. Mezclando tabla por jerarquía de clases con tabla por subclase
9.1.5. Tabla por clase concreta
9.1.6. Table per concrete class using implicit polymorphism
9.1.7. Mezclando polimorfismo implícito con otros mapeos de herencia
9.2. Limitaciones

Hibernate soporta las tres estrategias básicas de mapeo de herencia:

En adición, Hibernate soporta un cuarto, ligeramente diferente tipo de polimorfismo:

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 <subclass>, <joined-subclass> and <union-subclass> mappings under the same root <class> element. It is possible to mix together the table per hierarchy and table per subclass strategies under the the same <class> element, by combining the <subclass> and <join> elements (see below for an example).

It is possible to define subclass, union-subclass, and joined-subclass mappings in separate mapping documents directly beneath hibernate-mapping. This allows you to extend a class hierarchy by adding a new mapping file. You must specify an 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.

Es posible usar estrategias de mapeo diferentes para diferentes ramificaciones de la misma jerarquía de herencia, y entonces usar polimorfismo implícito para conseguir polimorfismo a través de toda la jerarquía. Sin embargo, Hibernate no soporta la mezcla de mapeos <subclass>, y <joined-subclass> y <union-subclass> bajo el mismo elemento <class> raíz. Es posible mezclar juntas las estrategias de tabla por jerarquía y tabla por subclase, bajo el mismo elemento <class>, combinando los elementos <subclass> y <join> (ver debajo).

Un enfoque alternativo es hacer uso de polimorfismo implícito:

<class name="CreditCardPayment" table="CREDIT_PAYMENT">
    <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
>

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

La desventaja de este enfoque es que Hibernate no genera UNIONs de SQL al realizar consultas polimórficas.

Para esta estrategia de mapeo, una asociación polimórfica a Payment es mapeada generalmente usando <any>.

<any name="payment" meta-type="string" id-type="long">
    <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
>

Since the subclasses are each mapped in their own <class> element, and since 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 Payment interface.

<class name="CreditCardPayment" table="CREDIT_PAYMENT">
    <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
>

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

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

La siguiente tabla muestra las limitaciones de mapeos de tabla por clase concreta, y de polmorfismo implícito, en Hibernate.