Lets say we want to map this class hierarchy:
Table wise we only have one table called MultipleClassesToOneTable:
So we're trying to map MainClass and MainClassKind to a single table and we want it to handle the fact that MainClassKind has subclasses. Why are we doing this, because we're working with a pre-existing database that is hard to work with.
Ideally we want MainClassKind to behave like a <component> but we can't map it that way because <component> does not support inheritance so the question is how do we map it?
This is the class that would act as our aggregate root and which will manage the ID, its mapping is quite simple:
<id name="Id" column="Id">
<generator class="identity" />
<property name="Name" column="Name" />
<one-to-one name="Kind" access="property" cascade="all-delete-orphan" />
Note that this class is mapped to MultipleClassesToOneTable and its generating the identity value which is stored in Id. The class also has an association to a MainClassKind, but its a pretty dull ordinary mapping file.
If we could map this class as a component of MainClass then we would, since we can't we have to do something a bit more interesting:
<class name="MainClassKind" table="MultpleClassesToOneTable" lazy="false">
<id name="Id" column="Id" >
<discriminator column="Kind" insert="false" />
<property name="Kind" access="property"/>
<property name="Description" column="Description" />
<one-to-one constrained="true" name="MainClass" access="property"/>
<subclass discriminator-value="0" name="FirstKind" >
<property name="FirstClassesExtraValue" access="property"/>
<subclass discriminator-value="1" name="SecondKind"/>
So what is notable about this mapping:
- Generator - The Id is coming from the associated MainClass object.
- Discriminator Mapped Twice - The Kind column is mapped twice, once as the discriminator and once as a property. We only have the property mapping because for some reason when we use <discriminator> like this it doesn't update the associated column, I believe this is a bug. I've thus set insert="false" on the discriminator and mapped the property.
- Shared Row - As discussed we need to have a relationship back to the MainClass to allow us to use its Id. We could map this as a field but here I've included it as a property. Anyway it's mapped as a <one-to-one> and since both map to the same row they do technically have the same ID.
Well I'm not exactly happy with this mapping, it seems like a hacky way of getting the behaviour I want, but I guess its an option if you really want to redesign your model in such a way without redesigning your database. Is there a better way to handle this though?