Inheritance Mapping The Three Strategies TODO: While this is all still supported, many new features would require a rewrite of this whole chapter Hibernate supports the three basic inheritance mapping strategies. table per class hierarchy table per subclass table per concrete class (some limitations) It is even possible to use different mapping strategies for different branches of the same inheritance hierarchy, but the same limitations apply as apply to table-per-concrete class mappings. Hibernate does not support mixing <subclass> mappings and <joined-subclass> mappings inside the same <class> element. However, it is possible to use a <join> element to map this. Suppose we have an interface Payment, with implementors CreditCardPayment, CashPayment, ChequePayment. The table-per-hierarchy mapping would look like: ... ... ... ... ]]> Exactly one table is required. There is one big limitation of this mapping strategy: columns declared by the subclasses may not have NOT NULL constraints. A table-per-subclass mapping would look like: ... ... ... ... ]]> 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). Note that Hibernate's implementation of table-per-subclass requires no discriminator column. Other object/relational mappers use a different implementation of table-per-subclass which 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. TODO: document usage of join for discriminators in table-per-subclass TODO: document usage of join for mixing inheritance mapping strategies For either of these two mapping strategies, a polymorphic association to Payment is mapped using <many-to-one>. ]]> The table-per-concrete-class strategy is very different. ... ... ... ]]> Three tables were required. Notice that nowhere do we mention the Payment interface explicitly. Instead, we make use of Hibernate's implicit polymorphism. Also notice that properties of Payment are mapped in each of the subclasses. In this case, a polymorphic association to Payment is mapped using <any>. ]]> It would be better if we defined a UserType as the meta-type, to handle the mapping from type discriminator strings to Payment subclass. ]]> There is one further thing to notice about this mapping. 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 table-per-class or table-per-subclass inheritance hierarchy! (And you can still use polymorphic queries against the Payment interface.) ... ... ... ... ]]> Once again, we don't mention Payment 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. TODO: Document union-subclass for polymorphic-table-per-concrete-class mappings Limitations There are certain limitations to the "implicit polymorphism" approach to the table-per-concrete-class mapping strategy. There are somewhat less restrictive limitations to <union-subclass> mappings. (TODO) The following table shows the limitations of table-per-concrete-class mappings, and of implicit polymorphism, in Hibernate. Features of inheritance mappings Inheritance strategy Polymorphic many-to-one Polymorphic one-to-one Polymorphic one-to-many Polymorphic many-to-many Polymorphic load()/get() Polymorphic queries Polymorphic joins Outer join fetching table-per-class-hierarchy <many-to-one> <one-to-one> <one-to-many> <many-to-many> s.get(Payment.class, id) from Payment p from Order o join o.payment p supported table-per-subclass <many-to-one> <one-to-one> <one-to-many> <many-to-many> s.get(Payment.class, id) from Payment p from Order o join o.payment p supported table-per-concrete-class (implicit polymorphism) <any> not supported not supported <many-to-any> use a query from Payment p not supported not supported table-per-concrete-class (union-subclass) <many-to-one> <one-to-one> <one-to-many> (for inverse="true" only) <many-to-many> s.get(Payment.class, id) from Payment p from Order o join o.payment p supported