Bidirectional one-to-many with an indexed collectionHibernate does not support bidirectional (inverse="true") one-to-many associations with an indexed collection (list, map or array) as the "many" end. If you want to keep the inverse="true" attribute and want to use an indexed collection, you have to handle the index of the collection manually. The following solution works with a list. The same method can be used when using an array or a map. (See below)
Mapping
<class name="net.sf.test.Parent" table="parent">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<list name="children" lazy="true" inverse="true">
<key column="parent_id"/>
<index column="index_col">
<one-to-many class="net.sf.test.Child"/>
</list>
</class>
<class name="net.sf.test.Child" table="child">
<id name="id" column="id" type="long" unsaved-value="null">
<generator class="sequence">
<param name="sequence">SEQ_DEFAULT</param>
</generator>
</id>
<many-to-one name="parent" column="parent_id" not-null="true"/>
<property name="index" type="int" update="true" insert="true" column="index_col" />
</class>
The inverse="true" is set to the one side. The column name for the index property on the child is the same as the index column of the one-to-many mapping on the parent.
Code The implementation of the Child getIndex and setIndex methods is as follows:
public class Child
{
...
public int getIndex()
{
return this.getParent().getChildren().indexOf(this);
}
private void setIndex(int index)
{
// not used, calculated value, see getIndex() method
}
...
}
By having the index value calculated, Hibernate will mark all Childs that have their index changed dirty. (If you switch 2 items from place, when you insert a new child, ...)
Note: For arrays and maps, there will be a different implementation of the getIndex method. Map with String as keys:
public String getIndex()
{
if (this.getParent().getChildMap().containsValue(this)
{
// return the key value for this child
}
return null;
}
|