Full source code is provided in the package: de.laliluna.inheritance.xmlinclude This mapping is only possible with XML. It uses implicit polymorphism. We just do not specify any mapping for the parent class OldMusicGroup but use the inherited properties in our sub classes.
Classes | Tables |
The consequence of this approach is that we have to specify all common fields (id, name) for all mappings. We can reduce the effort using a XML include.
OldMusicFan mapping.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [<!ENTITY allproperties SYSTEM "bin/de/laliluna/example11/common.xml"> ] > <hibernate-mapping package="de.laliluna.example11"> <class name="OldMusicFan" table="toldmusicfan"> <id name="id"> <generator class="sequence"> <param name="sequence">tmusicfan_id_seq</param> </generator> <!-- MySQL generator for a increment field <generator class="increment"/> --> </id> <property name="name" type="string"></property> <set name="musicGroups" table="oldmusicfan_musicgroup"> <key column="musicfan_id"></key> <many-to-any meta-type="string" id-type="integer"> <meta-value class="OldBoyGroup" value="oldboy"/> <meta-value class="OldHardrockGroup" value="oldhardrock"/> <column name="musicgroup_class"></column> <column name="id"></column> </many-to-any> </set> </class> <class name="OldBoyGroup" table="toldboygroup"> &allproperties; <property name="cryingGroupies" type="boolean"></property> </class> <class name="OldHardrockGroup" table="toldhardrock"> &allproperties; <property name="destroyedGuitars" type="integer" not-null="true"></property> </class> </hibernate-mapping>
common.xml.
<id name="id"> <generator class="sequence"> <param name="sequence">tmusicfan_id_seq</param> </generator> <!-- MySQL generator for a increment field <generator class="increment"/> --> </id> <property name="name" type="string"></property>
The command [<!ENTITY allproperties SYSTEM "bin/de/laliluna/example11/common.xml"> ] will replace all occurrences of &allproperties; with the context of the common.xml file. An insert into a subclass will only result into an insert in one table. A query of all old music groups causes two queries to be issued, one for each subclass.
session.createQuery("from de.laliluna.inheritance.xmlinclude.OldMusicGroup") .list();
Very special is also the relation to music fan. We need to use a special kind of any mapping to allow Hibernate to retrieve the proper class. I recommend naming the second column with the same name as both field name and column name of the subclass.
<column name="musicgroup_class"></column> <column name="id"></column>
If you do not follow this, you can not issue a query like the following.
session.createQuery("select mf from OldMusicFan mf where mf.musicGroups.id in "+ "(select hg.id from OldHardrockGroup hg where hg.destroyedGuitars > 150) ") .list();
I consider this to be a Hibernate problem. My personal impression is that this is not at all a very beautiful mapping approach, especially when it comes to relations.