-->
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.  [ 10 posts ] 
Author Message
 Post subject: SortedSet, why does it UPDATE every element?
PostPosted: Tue Oct 03, 2006 5:33 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
I've got an object, a Transfer. I have TransferEvents I add to it and these are sorted by the timestamp of the event.

Why when I save the Transfer it INSERTs the new TransferEvent as expected. Yet Hibernate then also UPDATEs every TransferEvent as well. Why?

Is there something I've done wrong in defining the set in the hibernate mapping?

Hibernate version:
2.1

Mapping documents:
<class name="Transfer">
<id name="id" column="ID">
<generator class="native" />
</id>
<set name="events" cascade="all" sort="natural" inverse="true" >
<key column="TRANSFER_ID" foreign-key="FK_TRANSFER_EVENTS"/>
<one-to-many class="com.ncube.nable.platform.transfer.TransferEvent"/>
</set>
</class>

<class name="TransferEvent">
<id name="id" column="ID">
<generator class="native" />
</id>
<property name="message" />
<property name="eventTime" type="com.ncube.nable.platform.hibernate.DateTimeType" />
<property name="eventTypeName" />
<many-to-one name="transfer" column="TRANSFER_ID" cascade="none" not-null="true" />
</class>
SQL

14:25:19,380 DEBUG SQL:226 - insert into MC.TransferEvent (message, eventTime, eventTypeName, TRANSFER_ID, ID) values (?, ?, ?, ?, null)
14:25:19,380 DEBUG SQL:226 - call identity()
14:25:19,395 DEBUG hibernate:243 - Committing database transaction of this thread.
14:25:19,395 DEBUG SQL:226 - update MC.TransferClient set clientId=? where ID=?
14:25:19,395 DEBUG SQL:226 - update MC.Transfer set transferEnabled=?, status=?, created=?, priority=?, savedState=?, attempts=?, destHost=?, destFile=?, destUsername=?, destPassword=?, sourceHost=?, sourceFile=?, sourceUsername=?, sourcePassword=?, isCancelable=?, cancelOnRestart=?, transferReason=? where ID=?
14:25:19,395 DEBUG SQL:226 - update MC.TransferEvent set message=?, eventTime=?, eventTypeName=?, TRANSFER_ID=? where ID=?
14:25:19,395 DEBUG SQL:226 - update MC.TransferEvent set message=?, eventTime=?, eventTypeName=?, TRANSFER_ID=? where ID=?
14:25:19,395 DEBUG SQL:226 - update MC.TransferEvent set message=?, eventTime=?, eventTypeName=?, TRANSFER_ID=? where ID=?


Last edited by ckessel on Wed Oct 04, 2006 11:16 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 7:24 pm 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
You need to set unsaved-value="0" for the id of your child - other value for unsaved may make sense for your app.
http://www.hibernate.org/hib_docs/refer ... child.html


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 11:15 am 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
Why would unsaved value matter? In both cases I'm using a native generator on a Long. The Transfer, and any historical events, are all saved and have an generated, valid id. The new TransferEvent has a null for the id, so it should be a new one. And indeed, I see the INSERT for it and that makes sense, like I said before.

What doesn't make sense is why it UPDATES each TransferEvent after that insert. Nothing has changed for them.

This is going to be a real performance problem when I get to 100's of events. Each new event is going to cause hundreds of UPDATEs!

Edit: yea, unsaved-value isn't relevant in this case. From the chapter you referenced:

"unsaved-value defaults to "null", which is perfect for a Long identifier type."

I use a Long and a native generator, so I'm effectively using the default unsaved-value="null".


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 11:58 am 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
Ckessel,

IMHO hibernate thinks those objects have been modified, otherwise it would not try to save them. It seems I was wrong in tying this to unsaved-value, thanks for correcting me. I do not have experience with hibernate2, if you can isolate a test case I will try to compile it ...

Maybe somebody else will weight on this...

Marius


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 12:11 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
I turned up the logging looking for "dirty" messages while it notes the Transfer as dirty, it doesn't specifically note the events. It just cascades an save-update to the TransferEvents and eventually decides to update them all even though they don't need it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 1:03 pm 
Regular
Regular

Joined: Tue Sep 26, 2006 11:37 am
Posts: 115
Location: Sacramento, CA
Ckessel,

There is another setting that I cannot find right now which makes hibernate track which objects are dirty. It is on by default in Hibernate 3, I do not know what it is Hibernate 2. Maybe this is creating problems ....

Just trying to help out here :)

Marius


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 1:07 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
Heh, thanks for trying :). I'm not sure what setting to look for, but I have to fix this problem. I can see by looking into Hibernate's code for this log line that the TransferEvent must be seen as dirty, but I can't figure out why. I've done an equals() on every field in the object when it's loaded and before the save and nothing has changed.

09:44:35,114 DEBUG SessionImpl:2533 - Updating entity: [com.ncube.nable.platform.transfer.TransferEvent#2]

Edit (on logging): I've tried increasing logging to "trace" or "all", because I can see trace log levels in the Hibernate code I downloaded at one point. Yet, I never see any trace lines. If I downgrade to "info", the "debug" lines go away, so I know my log level changes are taking effect.

Did Hibernate remove trace level logging at some point? Or is there some other stupid trick I'm not understanding about using "trace" log levels?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 5:31 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
Well, I added mutable="false" to the <class> and <cache usage="read-only"/> and was able to get the updates to stop. TransferEvents, once added, are never going to be modified so these settings work in my case.

I don't understand why I needed to add them at all though and I feel a bit uneasy about Hibernate's collection checking at this point and whether it's going to be efficient.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 13, 2006 2:58 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
Ok, the mutable and cache settings won't work. I can't ever delete the TransferEvent's when we go through and finally delete the Transfer in a purge at some point.

Is there really no one that knows what's going on in this situation? Having Hibernate generate an update for each and every time in the sorted set whenever I add one new element is insane.

This is a complete performance killer and it seems like sorted sets have to be something people are using. Yes?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 13, 2006 3:52 pm 
Beginner
Beginner

Joined: Thu Dec 09, 2004 3:19 pm
Posts: 34
Ok, finally found a hack that works. Actually, 2 hacks.

1) Declare in <class> select-before-update="true".

If I put this setting in, it realizes the TransferEvent objects in the sorted set haven't changed. It prevents the update, but causes a bunch of new SELECT statements (obviously).

2) Declare each and every property in <class name="TransferEvent"> to have update="false".

This finally prevents Hibernate from trying to issue updates on my TransferEvents. Since TransferEvents never change once created, this is fine. Using mutable="false" in my <class> wasn't an option since I do delete TransferEvents via delete-orphan if the owning Transfer is deleted.

I tried adding update="false" to just one property at a time, wondering if it was any particular property that caused the problem. Nope, it's not. If any property lacks the update="false" setting, Hibernate issues an UPDATE for each TransferEvent in the SortedSet when I add a new TransferEvent to that set.

So, problem solved, sort of. Worked around anyway.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 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.