-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Bi-directional List-association with all-delete-orphan
PostPosted: Mon Jun 06, 2005 3:31 am 
Beginner
Beginner

Joined: Thu Jun 02, 2005 5:09 am
Posts: 22
Hi,

from the following pages, I got the impression that Hibernate 3 now supports bi-directional one-to-many associations using Lists by setting inverse="false" on the parent and mapping the list index as a read-only property of the child:

http://www.hibernate.org/193.html
http://www.hibernate.org/116.html#A9

I try to use this with cascade="all-delete-orphan" declared on the parent's list property. This does eventually result in the deletion of a child if I call parent.getChildren().remove(), but first Hibernate tries to decouple the child from the parent by setting the foreign key and list index to null.
Since this is a real parent/child relation, I have defined a non-null constraint on these columns so this causes an error. If I remove the constraint the delete will take place, but only after a useless update of a row that is to be deleted anyway.

I cannot find more documentation on if and if so, how this is supported and if it is supposed to work this way. Can anyone shed some light on this issue? Is the mapping using inverse="false" as described on the given pages the recommended way to use a bi-directional list-association in Hibernate 3, or should I resort to doing my own list index management and use a set mapping instead?

Hibernate version: 3.0.5

Mapping documents:

parent (only subclass shown; the where-clause is needed because there are other associations to other subclasses in the same table as explained here):
Code:
    <subclass name="Control" extends="Category" discriminator-value="CO">

        <!--  bi-directional list assocation, so no inverse -->
        <list name="controlItems" cascade="all-delete-orphan" where="T930_ITM_TYPE='CI'">
            <key column="T930_CAT_UUID"/>
            <index column="T930_ITM_LIST_INDEX"/>
            <one-to-many class="ControlItem" />
        </list>

    </subclass>


child (both super- and subclass mappings):
Code:
    <class name="Item" table="TB930_ITM" abstract="true" discriminator-value="null">

        <id name="id" unsaved-value="none">
            <column name="T930_ITM_UUID" not-null="true" sql-type="char(32)" />
            <generator class="assigned" />
        </id>

        <discriminator column="T930_ITM_TYPE" type="string" length="2" />

        <version name="serverVersion" type="int" column="T930_ITM_VERSION" access="property" unsaved-value="negative" />

        <!-- skipping some simple properties... -->

        <!--  read-only property used by Hibernate
                to manage bi-directional List associations
                from Category subclasses -->
        <property name="listIndex" column="T930_ITM_LIST_INDEX" type="int" update="false" not-null="true"/>
</class>


...and the subclass for the child:
Code:
    <subclass name="ControlItem" extends="Item" discriminator-value="CI">

        <many-to-one name="control">
            <column name="T930_CAT_UUID" not-null="true" sql-type="char(32)" />
        </many-to-one>

    </subclass>


The generated SQL on removal of the single ControlItem of a Control:
Code:
2005-06-06 09:03:18,224 DEBUG [main] org.hibernate.SQL - update TB920_CAT set T920_CAT_VERSION=?, T920_CAT_NAME_PRI=?, T920_CAT_NAME_SEC=?, T920_CAT_GUIDE_REF=?, T920_CAT_EFF_START=?, T920_CAT_EFF_END=?, T920_CAT_LAST_MUTATED=?, T920_CAT_LAST_MUTATED_BY=? where T920_CAT_UUID=? and T920_CAT_VERSION=?

2005-06-06 09:03:18,646 DEBUG [main] org.hibernate.SQL - update TB930_ITM set T930_CAT_UUID=null, T930_ITM_LIST_INDEX=null where T930_CAT_UUID=? and T930_ITM_TYPE='CI'

2005-06-06 09:03:18,693 DEBUG [main] org.hibernate.SQL - delete from TB930_ITM where T930_ITM_UUID=? and T930_ITM_VERSION=?


The first statement updates the version of the parent and the third removes the child, but I don't understand why Hibernate insists on calling the second statement if the row (yes, it is the same row, I checked the SQL bindings) is to be deleted.
When removing a child from a collection with multiple items the behaviour is the same: always an extra update nulling out the foreign key and list index before the delete in the same session/transaction.

Thanks in advance for any help on this subject.

Joris[/url]


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 08, 2005 4:20 am 
Beginner
Beginner

Joined: Thu Jun 02, 2005 5:09 am
Posts: 22
The solutions mentioned in the two pages I referred to in my previous posting are not exactly the same:

http://www.hibernate.org/193.html states the following:
Quote:
Parent
Code:
<list inverse="false"/>

Child
Code:
<many-to-one insert="false" update="false"/>



However, http://www.hibernate.org/116.html#A9 shows the following example:
Quote:
Code:
    <class name="eg.Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <list name="children" lazy="true">
            <key column="parent_id"/>
            <index column="child_order"/>
            <one-to-many class="eg.Child"/>
        </list>
    </class>

    <class name="eg.Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
        <property name="childOrder" column="child_order" type="int" update="false" not-null="true"/>
        <many-to-one name="parent" class="eg.Parent" column="parent_id" not-null="true"/>
    </class>


So, the first page places the update="false" on the many-to-one element, while the second maps the index as a property that is made read/insert-only.

I would really appreciate an answer from the Hibernate team on what the supported and appropiate mappings for a bi-directional List association are in Hibernate 3, since my application has the need for quite a few of these associations.
I can't find either of the two shown solutions in the documentation: in fact, I can't find any docs besides the two pages mentioned that explain the new support for bi-directional List associations supposedly added in Hibernate 3...

TIA

Joris


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 10:35 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
<key not-null="true" ... />


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 10:36 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
eg. see org.hibernate.test.unidir


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 10:39 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Of course this is documented in the reference since H3 is out.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 10:48 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
You're right. I posted in this thread 'cos I thought maybe the documentation might have been a bit weak on that point. Now I see it is clearly documented in *three* different places, including this:

http://www.hibernate.org/hib_docs/v3/re ... oreignkeys

and this:

http://www.hibernate.org/hib_docs/v3/re ... ration-key

and this:

http://www.hibernate.org/hib_docs/v3/re ... tional-12m

hrmmmm.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 11:21 am 
Beginner
Beginner

Joined: Thu Jun 02, 2005 5:09 am
Posts: 22
All the pages you mention are for uni-directional associations, not bi-directional. Of course, the same goes for org.hibernate.test.unidir.
Anyway, I had defined a non-null constraint originally, but as explained in my first posting this caused violations since Hibernate tried to set both the index and foreign key to null before the deleting the child row. Maybe I wasn't clear on that, but the constraint violation itself is not the major problem I'm experiencing, so I removed the constraint from the mapping I posted.

I still can't find anything in the docs about bi-directional associations using a List used in the way as described on the web pages I mentioned. Since the two pages don't even describe the same solution, I find this very confusing: your answers, though much appreciated, just add to my confusion since I can't see how they're relevant to my situation where my parent-child relationship is bi-directional. Or should the inclusion of the

Could you please review the docs on the pages I referred to and tell me if one of the solutions described there for Hibernate 3 is actually supported? I can't find the solutions on this pages documented in the reference documentation, though I'm quite sure that I double-checked that before posting on the forum.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 1:01 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Well, when you can tell me what a "bidirectional list" could *possibly* mean, I'll show you how to do it in Hibernate. Exactly how am I supposed to figure out the index from the Child end?? Until then, use two unidirectional associations.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 1:02 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Anyway, I had defined a non-null constraint originally, but as explained in my first posting this caused violations since Hibernate tried to set both the index and foreign key to null before the deleting the child row.


This is not true, you obviously did not use <key not-null="true">.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 13, 2005 1:13 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Well, I guess these things that seem so obvious can be nonobvious to some people.

Here you go:

Code:
<class name="Parent">
   <id name="name"/>
   ...
   <list name="children" cascade="all,delete-orphan">
      <key column="parentName"
         not-null="true"
         update="false"/>
      <list-index column="sibling"/>
      <one-to-many class="Child"/>
   </list>
</class>
   
<class name="Child">
   <id name="name"/>
   ...
   <many-to-one name="parent"
      column="parentName"
      not-null="true"
      insert="false"
      update="false"/>
</class>



The update="false" bits are not absolutely necessary, but result in more efficient SQL.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 01, 2005 6:46 am 
Newbie

Joined: Mon Aug 01, 2005 6:07 am
Posts: 2
I'd be happy if you could clarify some more points:

When mapping an association exacly like the example you gave before, can I expect that list indexes in the db are automatically reorganized by Hibernate 3 on modifications?

- If yes, can I expect that automatic list numbering works also with <list-index base="1"/>
--> when adding a new element to a collection, the db column does not get a 1-based index, but instead the 0-based index of the list, resulting in a duplicate index

- If yes, can I expect that deleting an element in the middle of a list results in updating (decrementing) the list indexes of the consecutive elements?
--> is apparently not the case, thus resulting in null-elements when reading the list the next time from the db

Thanks in advance for your help


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 24, 2005 2:05 pm 
Newbie

Joined: Wed Aug 24, 2005 1:53 pm
Posts: 4
Dear flo,
Your list-index will be re-ordered no matter how you change the list. I tested. The base="1" has the said behaviour as the doc.

However, you must be very clear to not-null="true", insert="false" and update="false". All of them are the key to have an efficient SQL to database.


I searched for a whole afternoon to solve the INSERT problem. My problem is the child record having INSERT then UPDATE statement to DB. Gavin pointed out the update="false" in <key/> tag solve all the problem. Now, all records have the according 1 INSERT statement to execute.


Last but not lease, this is a great link for the usage of <list> and <list-index>. Gavin explained very clearly and showed an excellent example. Thank you very much.


Top
 Profile  
 
 Post subject: interesting
PostPosted: Mon Sep 05, 2005 6:20 am 
Newbie

Joined: Thu Jan 22, 2004 5:07 am
Posts: 9
gavin wrote:
Well, when you can tell me what a "bidirectional list" could *possibly* mean, I'll show you how to do it in Hibernate. Exactly how am I supposed to figure out the index from the Child end?? Until then, use two unidirectional associations.


I always took "bi-directional" to imply the existence of two methods:

Parent.getChildren() {}
and
Child.getParent() {}

In that case, one could have a bi-directional list. What I'm hearing is that hibernate supports bi-directional lists (in this sense), but not bi-directional lists with inverse="true".

Couldn't hibernate support this kind of relationship for Parent objects loaded from a hibernate session since their lists are proxy objects? Each time an object gets added to a persistent parent object, hibernate would update a Session-wide map of all the List collections to which the object belonged. Then, when a client asks hibernate to save the Child object, it checks the references, grabs the parent keys and indexes, and saves them with the rest of the Child's data.

Seems like hibernate already does this to support bi-directional sets with inverse="true" . . . just without the indexes.


Top
 Profile  
 
 Post subject: Parent-child list not functioning
PostPosted: Mon Oct 23, 2006 4:14 am 
Newbie

Joined: Thu Oct 19, 2006 11:28 am
Posts: 4
I feel some additional information in this thread would be helpful to new users (like myself). Gavin posted an "obvious" example of a parent-child list mapping. What would be the (equally obvious) manner in which someone would invoke a new child and persist it to the parent?

As I understand it, it involves something like this:

Code:
/* Calling (UI) level */

p = hibernateManager.getParent(id);
c = new Child();

p.add(c);

hibernateManager.parentSaveOrUpdate(p);

/* Within Parent class */

public void add(Child c) {
    c.setParent(this);
    this.childList.add(c);
}


Using Gavin's mapping, performing this gives me a DataException - "Could not execute JDBC batch update" resulting from a meaningless update on the parent's fields/properties. Please see my other post. http://forum.hibernate.org/viewtopic.php?t=966178

P.S. I have tried all of this with both Hibernate 3.1.3 and the new 3.2 release.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 21, 2006 12:29 pm 
Newbie

Joined: Tue Sep 26, 2006 8:34 am
Posts: 16
Location: Paris, France
i finally solve my issue which look similar to your's

check http://forum.hibernate.org/viewtopic.php?t=968296


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next

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.