I'm using Hibernate 2.1 and McKoi 1.0.2.
Problem: null values in referenced subclass. Please read the following for a full description.
The following mapping represents a Device that has a one-to-many relationship with BaseItem. BaseItem has two subclasses Item and ArrayItem. The ArrayItem has a one-to-many relationship with its sibbling subclass Item.
Code:
* 1
BaseItem --------------- Device
^
|
-------------------------------
| |
| * 1 |
Item --------------------- ArrayItem
<hibernate-mapping>
<class name="dvs.summit.data.items.BaseItem" discriminator-value="base">
<id name="id" type="long" column="id" unsaved-value="null">
<generator class="hilo"/>
</id>
<many-to-one name="device" column="device_id" class="dvs.summit.devices.DeviceData"/>
<many-to-one name="itemDefinition" column="itemDef_id" class="dvs.summit.data.ItemDefinition"/>
<property name="itemIndex" column="itemIndex" type="integer"/>
<subclass name="dvs.summit.data.items.Item" table="Item" discriminator-value="item">
<property name="arrayIndex" column="arrayIndex" type="integer"/>
<property name="valueId" column="value_id"/>
<many-to-one name="owningArray" column="arrayItem_id"/>
<subclass name="dvs.summit.data.items.StringItem" discriminator-value="string"/>
...
<subclass name="dvs.summit.data.items.AlarmItem" discriminator-value="alarm"/>
</subclass>
<subclass name="dvs.summit.data.items.ArrayItem" table="ArrayItem" discriminator-value="array">
<list name="items" inverse="true" cascade="all">
<key column="arrayItem_id"/>
<index column="arrayIndex"/>
<one-to-many class="dvs.summit.data.items.Item"/>
</list>
<subclass name="dvs.summit.data.items.StringArrayItem" discriminator-value="string-array"/>
<subclass name="dvs.summit.data.items.AlarmArrayItem" discriminator-value="alarm-array"/>
</subclass>
</class>
</hibernate-mapping>
If I create a new instances of ArrayItem and its referenced Items the data in the database
looks something like this
Code:
id type device_id itemIndex arrayIndex arrayItem_id
---------------------------------------------------------------------
3408050 alarm-array 524291 33 null null
3408051 alarm 524291 33 0 3408050
3408052 alarm 524291 33 1 3408050
3408053 alarm 524291 33 2 3408050
If I update the array items the data in the database suddenly contains null values for
device_id and itemIndex:
Code:
id type device_id itemIndex arrayIndex arrayItem_id
---------------------------------------------------------------------
3408050 alarm-array 524291 33 null null
3408051 alarm null null 0 3408050
3408052 alarm null null 1 3408050
3408053 alarm null null 2 3408050
The reason is that hibernate is doing the following. It first updates the AlarmArrayItem correctly
update Item set device_id=?, itemDef_id=?, itemIndex=? where id=?
Updating entity: [dvs.summit.data.items.AlarmArrayItem#3408050]
Dehydrating entity: [dvs.summit.data.items.AlarmArrayItem#3408050]
binding '524291' to parameter: 1
id unsaved-value strategy NULL
binding '3375176' to parameter: 2
binding '33' to parameter: 3
binding '3408050' to parameter: 4
Then it updates the items collection by first (sort of) deleting the whole collection and then refill all items again.
Deleting collection: [dvs.summit.devices.DeviceData.items#524291]
update Item set device_id=null, itemIndex=null where device_id=?
binding '524290' to parameter: 1
done deleting collection
done closing: 0 open PreparedStatements, 0 open ResultSets
closing statement
Inserting collection: [dvs.summit.devices.DeviceData.items#524291]
about to open: 0 open PreparedStatements, 0 open ResultSets
update Item set device_id=?, itemIndex=? where id=?
preparing statement
binding '524291' to parameter: 1
id unsaved-value strategy NULL
binding '3407873' to parameter: 3
binding '0' to parameter: 2
...
The problem is that it now wiped out device_id and itemIndex for all items refrenced by an arrayItem!
How can I prvent Hibernate from doing the "Deleting collection: [dvs.summit.devices.DeviceData.items#524291]" thing?
I should be able to bypass this by persisting Items and ArrayItems in two seperate tables (table-per-concrete-class since joined-subclass does not allow the subclass element) but will then lose foreign key constraint capability.