-->
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: Problem removing child object from collection after saving
PostPosted: Fri Jul 01, 2005 1:40 am 
Newbie

Joined: Fri Jun 03, 2005 4:08 am
Posts: 12
Hi,

I'm having problems removing a child object from a collection immediately right after saving it.

The use case that fails for me is as follows:
1. I load the parent with all the existing children.
2. I add a new child.
3. I call saveOrUpdate.
4. New child appears on the database and is given a generated primary key.
5. I remove the newly added child from the collection using...

//assuming someLastName String is unique per record
Set children = parent.getChildren();
for (Iterator i = children.iterator(); i.hasNext();) {
Child child = (Child) i.next();
if ("someLastName".equals(child.getLastName())) {
log.debug("Object found. Removing child from collection...");
log.debug("Removing..." + child);
children.remove(child);
break;
}
}

..but after that block executes, the child is still in the Collection!

Note that that block of code works for Child objects that are NOT newly added, i.e. children that were already there when i loaded the parent in the first place. Once again, only newly added child objects cannot be removed from the collection.

Any ideas?

Thanks,
-Yves-


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 4:46 am 
Regular
Regular

Joined: Thu Apr 29, 2004 5:08 pm
Posts: 56
Location: Montreal, Quebec, Canada
Salut Yves,

What is important here are your Session and Transaction boundaries + where you call session.flush(), if you do so (transaction.commit() can do it)

open session
begin transaction

load parent + all children
create new child
add new child to parent's children collection

save parent, cascading is done to parent.children, assuming you at least have the save-update cascading style.

[Note: if you use an id generator (identity, sequence, native) whose ids are generated by the database itself, the sql insert is issued right away because hibernate needs to know this id! He uses it to cache the retreived object(s) in session.
Using other generators like Increment, Assigned, the insert statement is simply added to the batcher. When calling session.flush() (or transaction.commit(), calling it) entities are dirty checked (you can disable this behavior if you want in HB3) and the batcher is executed. Only at this point hb hits the db.]

remove newly added child from parent's children collection

[Note: here, it depends how you set the inverse attribute of your collection and if this relation is bidirectional, back in the mapping files. If you set inverse="true" from the one-to-many side, removing the entity from the parent's children collection isn't enuff. You must also set the children->parent reference to null (for a bidirectional relation with inverse=true from the one-to-many side]

flush session

collection and database should be synchonized, one less child.

commit transaction

close session

For the entity not removed from the collection itself, .equals() and .hashCode() on your entities is important, you must respect the rule: don't use entity id (if not using an assigned natural key even if not recommended) in hashCode() and equals() ovverrides.

[/list]

_________________
- Frank


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 6:06 am 
Newbie

Joined: Fri Jun 03, 2005 4:08 am
Posts: 12
Salut Frank,

Here are more details about my setup: it is indeed a bi-directional association with inverse="true" on the one-many side and cascade="all-delete-orphan"

The thing is i don't call save (or flush) right away because I want the removal to be temporary until the user actually clicks on "save" to finalize the changes. Only then do I call on "saveOrUpdate" (I use Spring's hibernateTemplate by the way).

But the problem is that Set.remove() does not even seem to work at all, even though I'm using the same actual object reference as a parameter for Set.remove().

When I use a debugger, right after the call to Set.remove(), I can see that nothing's happened and the object is really still there in the collection.

Since its the same object reference, would it be safe to assume that there is no doubt equals() and hashCode() will add up to the same value?

Any more ideas on what could make Set.remove() fail?

Once again, this only happens with newly added Children...

Thanks,
-Yves-


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 6:55 am 
Regular
Regular

Joined: Thu Apr 29, 2004 5:08 pm
Posts: 56
Location: Montreal, Quebec, Canada
First, I think it is a bad idea, a bad practice to call .remove() before the save button is clicked.

When the button is clicked, the code should look like:

open session
begin transaction

parent.removeChild( child );

session.flush (optional if right flush mode)

commit transaction

if catch exception( rollback transaction)

finally, close session.

You *must* override .equals and .hashCode for your entities. The default .equals() reference comparaison isn't enough since hibernate can instantiate proxies.

Read the HB doc to know how to override .equals and .hashCode as indicated.

_________________
- Frank


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 01, 2005 7:07 am 
Newbie

Joined: Fri Jun 03, 2005 4:08 am
Posts: 12
Its OK now.

It was in the equals() and hashCode() methods of the child class -- I was using a combination of the database identifier and a unique business key. I confined it now to simply using the unique business key as mentioned in the docs.

Merci!


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.