I have an interesting situation with trying to map a class heirarchy, and can't seem to find the best solution for it. I was using hibernate 2.0, but have upgraded to 3.0 as there appears to be more flexibility with its mappings.
I have two tables like so:
Code:
+---------------+
|template |
+---------------+
| id int |
| type varchar |
| other data... |
+---------------+
/\
||
+-----------------+
| instance |
+-----------------+
| id int |
| template_id int |
| other data... |
+-----------------+
And I have this java class heirarchy:
Code:
AbstractTemplate ==> TypeATemplate
|| ==> TypeBTemplate
|| ==> TypeCTemplate
\/
AbstractInstance ==> TypeAInstance
==> TypeBInstance
==> TypeCInstance
Basically, instances relate to templates as one-to-many, and I wanted instances to subclass templates as there properties and associations on the template which I want the instance to have too.
I've been trying to map this as table-per-subclass strategy.
But the concrete template types, and the concrete instance types, I wanted them all to switch on the same discriminator, which is the "type" column in the "template" table.
I've tried several combinations of <class> <subclass>, <join>, <joined-subclass> and use, or not, of <discriminator> for these 8 classes (2 abstract, 6 concrete)
The best I came up with was:
Code:
<class name="AbstractTemplate" table="template">
<id name="id" column="id"><generator class="native"/></id>
<discriminator column="type"/>
<property ..(many of).. />
<subclass name="TypeATemplate" discriminator-value="A"/>
<subclass name="TypeBTemplate" discriminator-value="B"/>
<subclass name="TypeCTemplate" discriminator-value="C"/>
<subclass name="AbstractInstance">
<join table="instance" fetch="select">
<key column="template_id"/>
<property ..(many of)../>
<subclass name="TypeAInstance" discriminator-value="A"/>
<subclass name="TypeBInstance" discriminator-value="B"/>
<subclass name="TypeCInstance" discriminator-value="C"/>
</join>
</subclass>
</class>
With this, things are almost working, and all the templates are happliy mapped. But the instances - when loading them, instead of hibernate finding each one, it finds the first of each (according to template's id value) duplicated by the number of each in the database (in the instance table).
What I think I need is for AbstractInstance to map its own id value, which means it needs to be a class, not a subclass, with the AbstractTemplate being a mapped association - but then how do I switch on the discriminator?
Is the solution just to have a duplicate discriminator in the instance table? (The rows in "instance" are generated with reference to "template")
I also considered changing the heirarchy to that TypeAInstance subclasses TypeATemplate, and AbstractInstance becomes just an interface (in C++ I would have used multiple-inheritance) but I'm not keen to do this, as there's a fair portion of code in AbstractInstance which would have to be duplicated within each concreate TypeXInstance.
Any suggestions?
Cheers,