-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: one-many bi-dir using List. idx is null in table.
PostPosted: Thu Apr 13, 2006 10:36 am 
Beginner
Beginner

Joined: Tue Oct 07, 2003 4:41 am
Posts: 21
I have a class Test4 which owns a collection of Test5's. The collection is implemented as a List. The Test5 class also has a reference back to Test4 so this is a bi-directional one-many association.

When I save an instance of Test4 it saves fine, as do the instances of Test5 in it's collection, but the idx column in the table for Test5 is null after the inserts. This then oviously causes problems when I try to retrieve that instance of Test4.

If I change the association to not be bi-directional and instead have 2 seperate associations, things work fine and the idx column gets the values as expected.

I can't see what the problem is, and whether it's a bug in my code, mapping files or in Hibernate.

Any help much appreciated.

John


Hibernate version:
3.1

Mapping documents:
Mapping file for Parent class. (Test4)

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ims.testonly.domain.objects.Test4" table="test_test4" lazy="true" discriminator-value="null" >
<id name="id" access="field" type="integer" unsaved-value="null">
<column name="id" sql-type="numeric(10,0)"/>
<generator class="native"/>
</id>
<discriminator not-null="false" length="4"/>
<version name="version" column="vstp" access="field"/>
<property name="isRIE" type="boolean" access="field" update="true">
<column name="rie" not-null="false" unique="false" />
</property>
<component name="systemInformation" class="ims.domain.SystemInformation" access="field" >
<property name="creationDateTime" type="timestamp" access="field">
<column name="sys_creation_datetime" />
</property>
<property name="lastUpdateDateTime" type="timestamp" access="field">
<column name="sys_lastupdate_datetime" />
</property>
<property name="creationUser" type="string" access="field">
<column name="sys_creation_user" length="30" />
</property>
<property name="lastUpdateUser" type="string" access="field">
<column name="sys_lastupdate_user" length="30" />
</property>
</component>
<list name="collt5" inverse="true" access="field" cascade="all-delete-orphan" lazy="true" >
<key >
<column name="t4parent" sql-type="numeric(10,0)" unique="false" />
</key>
<index column='idx'/>
<one-to-many class="ims.testonly.domain.objects.Test5"/>
</list>
<property name="namet4" type="string" access="field" update="true">
<column name="namet4" not-null="false" unique="false" />
</property>
</class>
</hibernate-mapping>


and Mapping for child class, Test5

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ims.testonly.domain.objects.Test5" table="test_test5" lazy="true" discriminator-value="null" >
<id name="id" access="field" type="integer" unsaved-value="null">
<column name="id" sql-type="numeric(10,0)"/>
<generator class="native"/>
</id>
<discriminator not-null="false" length="4"/>
<version name="version" column="vstp" access="field"/>
<property name="isRIE" type="boolean" access="field" update="true">
<column name="rie" not-null="false" unique="false" />
</property>
<component name="systemInformation" class="ims.domain.SystemInformation" access="field" >
<property name="creationDateTime" type="timestamp" access="field">
<column name="sys_creation_datetime" />
</property>
<property name="lastUpdateDateTime" type="timestamp" access="field">
<column name="sys_lastupdate_datetime" />
</property>
<property name="creationUser" type="string" access="field">
<column name="sys_creation_user" length="30" />
</property>
<property name="lastUpdateUser" type="string" access="field">
<column name="sys_lastupdate_user" length="30" />
</property>
</component>
<many-to-one name="t4Parent" class="ims.testonly.domain.objects.Test4" access="field">
<column name="t4parent" sql-type="numeric(10,0)" not-null="false" unique="false" />
</many-to-one>
<property name="name" type="string" access="field" update="true" >
<column name="name" length="100" not-null="false" unique="false" />
</property>
</class>
</hibernate-mapping>

Name and version of the database you are using:
SQLServer 2000.

The generated SQL (show_sql=true):

Hibernate: insert into test_test4 (vstp, rie, sys_creation_datetime, sys_lastupdate_datetime, sys_creation_user, sys_lastupdate_user, namet4) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into test_test5 (vstp, rie, sys_creation_datetime, sys_lastupdate_datetime, sys_creation_user, sys_lastupdate_user, t4parent, name) values (?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into test_test5 (vstp, rie, sys_creation_datetime, sys_lastupdate_datetime, sys_creation_user, sys_lastupdate_user, t4parent, name) values (?, ?, ?, ?, ?, ?, ?, ?)


As you can see, no mention of the idx column on the Test5 inserts even though it's in the mapping document.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 1:19 am 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
The Hibernate doc indicates that, for a bidirectional list relationship, the index column should be mapped on the child side as a persistent property (ie, the child entity should know its position in the list, not just the reference to the parent list).

Also, the doc refers to the <list-index...> element, instead of the <index...>. The DTD shows both, though. I don't know that the difference is.

There is an example in the 'Bidirectional associations with indexed collections' section of the doc for a Map instead of a List, but it looks like they are suggesting:
<list name="collt5" access="field" cascade="all-delete-orphan" lazy="true" >
<key>
<column name="t4parent" sql-type="numeric(10,0)" unique="false" not-null="true"/>
</key>
<list-index column="idx"/>
<one-to-many class="ims.testonly.domain.objects.Test5"/>
</list>

and, in Test5,
<many-to-one name="t4Parent" class="ims.testonly.domain.objects.Test4" access="field" insert="false" update="false">
<column name="t4parent" sql-type="numeric(10,0)" not-null="true" unique="false" />
</many-to-one>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 24, 2006 6:20 am 
Beginner
Beginner

Joined: Tue Oct 07, 2003 4:41 am
Posts: 21
Hi,

thanks for your response.
I found the place in the ref doc you referred to.

I made the change to add 'idx' as a property to Test5 and changed to Test4 mapping file to use <list-index> element.

This works fine, but I realised that I would have to write the code now to set the idx value on all the Test5 instances before the save of Test4. Once I did that things worked fine.

But in fact, I think I'll drop the bi-directionality of the association, and simply work with 2 seperate associations. A one-to-many from Test4 to Test5 and a many-to-one from Test5 to Test4.
Doing this means that from a coding perspective I still effectively have a bi-directional association, but I don't have to explicitly set the idx values in the Test5 instances, and can drop the idx property from Test5.
Of course this means I end up with an extra column in the Test5 table, but I can live with that for the sake of simplified code.

thanks

John


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 24, 2006 2:50 pm 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
The idx property is a requirement for a list-type collection, I believe. This is to preserve the symantics of a list, which is supposed to be an ordered collection. Without the idx property, rereading the parent would potentially return the list with elements in a different order than they were in when the parent entity (and children) were saved. If you don't care about the order, you can use a bag (or idbag) or set in your mapping.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 25, 2006 5:09 am 
Beginner
Beginner

Joined: Tue Oct 07, 2003 4:41 am
Posts: 21
I do care about the order in this case, but I've found that I don't need an explicit property in the child class (Test5) for 'idx' once the association is uni-directional.

It's sufficient to have it as the <index> column name in the parent (Test4) mapping file, and hibernate sets the values according to where the instances are in the list, and then on retrieval puts the instances into the list in the location specified by the value in the idx column.

This is nice and automatic and means I don't have to expose the idx property at all. The programmer simply has to order the child list correctly before saving.

It was just that I expected the same behaviour when I made the association bi-directional. Working fine though with the 2 uni-directional associations, and order is being preserved without idx as a property in Test5.

John


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.