Hello -
I'm using Hibernate3.1rc2.
I have a java class hierarchy that is quite deep, where everything is inherited through a single entity class :-
class Entity
class NamedEntity extends Entity
class SoftEntity extends NamedEntity
class SoftProperty extends NamedEntity
class Component extends NamedEntity
class XmlData extends Component
I use table-per-hierarchy mapping (in general), but I don't want 'Entity' to be the root - otherwise it would end up being 1-table-for-everything.
Instead, Entity, Component, SoftEntity are root-level classes in the mapping file, and have the same properties. i.e:
<class name="Entity"> ...
<subclass name="NamedEntity">
</class>
<class name="SoftEntity>...
<class name="SoftProperty>...
<class name="Component">
<subclass name="XmlData">...</subclass>
</class>
This is all good and works fine, except that the "Component" entity must have a many-many association back to 'Entity'.
In my mapping file I had the following inside component:
<set name="associatedClasses" table="ASSOCIATEDITEMS">
<key column="COMPONENT_ID" not-null="true" />
<many-to-many column="ENTITY_ID" unique="true" class="Entity"/>
</set>
When writing to the database however, hibernate complains of
'instance not of expected entity type'.
Reading back on the documentation, I'm guessing this is because it has no way of telling that the class type, and that I need to use a
<many-to-any> type association (though it implied this was just because reads won't generate a UNION statement, which I understand, though it would seem to be a problem for writing as well).
Is this correct? There aren't many details about how many-to-any is meant to operate. Is there a more preferable technique for splitting up 'deep' single-rooted inheritance hierarchies into multiple table-per-subclass-hierarchys ? It seems a shame that I can query for 'java.lang.Object' and get back all defined objects implicitly, but I can't if it's part of an association..
Mapping documents:
(fragment)
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="Entity" table="ENTITY">
<id name="Id"
type="MyOIDUserType">
<column name="ID" length="16" sql-type="BINARY(16)" />
</id>
<discriminator column="MTYPE" type="string" />
<subclass name="NamedEntity" >
<property name="name" type="string" length="50"/>
</subclass>
</class>
<class name="SoftEntity">
<id name="Id"
type="MyOIDUserType">
<column name="ID" length="16" sql-type="BINARY(16)" />
</id>
<discriminator column="MTYPE" type="string" />
<set name="softProperties" inverse="true">
<key column="SOFTENTITY_ID" />
<one-to-many
class="SoftProperty" />
</set>
</class>
<class name="SoftProperty" table="SOFTPROPERTY">
<id name="Id"
type="MyOIDUserType">
<column name="ID" length="16" sql-type="BINARY(16)" />
</id>
<discriminator column="MTYPE" type="string" />
<property name="Value" column="Value" type="string" length="256"/>
<many-to-one name="parent" column="SOFTENTITY_ID" not-null="true"/>
</class>
<class name="Component" table="COMPONENT">
<id name="Id"
type="MyOIDUserType">
<column name="ID" length="16" sql-type="BINARY(16)" />
</id>
<discriminator column="MTYPE" type="string" />
<set name="associatedClasses"
table="ASSOCIATEDITEMS">
<key column="COMPONENT_ID" not-null="true" />
<many-to-many column="ENTITY_ID" unique="true"
class="Entity" />
</set>
<subclass
name="XmlData">
<!-- Publication items -->
<property name="Name" column="PUBNAME" type="string"
not-null="false" length="128" />
<many-to-one name="documentRoot"
class="XmlData"
column="DOCROOT" />
</subclass>
</class>
</hibernate-mapping>
|