HIBERNATE JBoss.org
 |  Register  | 
     
News 
About 
   Feature List 
   Road Map 
Documentation 
   Related Projects 
   External Documentation 
Download 
Forum & Mailinglists 
Support & Training 
JIRA Issue Tracking
Wiki Community Area


Hibernate Public Training Courses


Get Hibernate in Action eBook!


JavaWorld 2003 Finalist


Jolt Award 2004 Winner
      
Documentation > Community Area > Bidirectional one-to-many with an indexed collection

Bidirectional one-to-many with an indexed collection

Hibernate 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;
  }
      

coWiki