-->
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.  [ 2 posts ] 
Author Message
 Post subject: saveOrUpdate() issuing update instead of insert
PostPosted: Mon Jun 01, 2009 8:00 pm 
Newbie

Joined: Mon Jun 01, 2009 7:23 pm
Posts: 2
Hi

I am doing an upgrade of Hibernate from 2.1.8 to 3.3.1. While testing the upgrade, I am facing with a weird scenario.

The application is creating a new hibernate object, and calling SessionImpl.saveOrUpdate(obj); to save that to the database. And it was working good in 2.1.8. But when the new jars for 3.3.1 are added, this method some how assumes the object as a detached entry and proceed with updating the object. But since it is a new entry, there is nothing to update in database, and hence is throwing the following error while flushing the session at the end of the request

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:47)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2431)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)


The trace goes all the way to DefaultSaveOrUpdateEventListener as per the logs, and it enters protected int getEntityState(...) and goes to if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) condition. This if condition is returning false hence by making hibernate assume that it is a detached instance.

The id attribute is generated for the object, and its definition is as below. There is no unsaved-value defined explicitly leaving it to default

<id name="assetId" type="long" column="ASSET_ID">
<generator class="assigned" />
</id>


How ever, when the same code is executed in 2.1.8, the functionality saves perfect. The trace on 2.1.8 goes to SessionImpl.saveOrUpdate(Object obj), the EntityEntry e = getEntry(object); returns a null, so go to else case and then calls save(obj); which is the expected case

Not sure why in 3.3.1, the entry is considered as detached instance on the first place, which is leading it to update the detached instance and fail at end breaking the application.

Immediately after the save is issued, I see the following trace from Hibernate Debug

org.hibernate.engine.IdentifierValue [4] [processAutoDecline] - id unsaved-value strategy NULL
org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating detached instance
org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating [com.i21.epay.model.AssetHolder#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - calling onUpdate()
31 May 2009 20:38:36 INFO [WebContainer : 1] com.insurance21.framework.service.BusinessObject [4] [processAutoDecline] - in onUpdate
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.financialAccts#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.autopayMemberHistory#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.assetDiaries#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.autoPayAgreement#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.enrollmentInfo#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.ReattachVisitor [4] [processAutoDecline] - collection dereferenced while transient [com.i21.epay.model.AssetHolder.noticeWaivers#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating [com.i21.epay.model.AssetHolder#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.Cascade [4] [processAutoDecline] - processing cascade ACTION_SAVE_UPDATE for: com.i21.epay.model.AssetHolder
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.Cascade [4] [processAutoDecline] - cascade ACTION_SAVE_UPDATE for collection: com.i21.epay.model.AssetHolder.autopayMemberHistory
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.CascadingAction [4] [processAutoDecline] - cascading to saveOrUpdate: com.i21.epay.model.AutoPayMemberHistory
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.IdentifierValue [4] [processAutoDecline] - id unsaved-value strategy NONE
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.AbstractSaveEventListener [4] [processAutoDecline] - detached instance of: com.i21.epay.model.AutoPayMemberHistory
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating detached instance
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating [com.i21.epay.model.AutoPayMemberHistory#component[partitionId,assetId,historySeqNum]{historySeqNum=1, partitionId=272100, assetId=10000721}]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - calling onUpdate()
31 May 2009 20:38:36 INFO [WebContainer : 1] com.insurance21.framework.service.BusinessObject [4] [processAutoDecline] - in onUpdate
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating [com.i21.epay.model.AutoPayMemberHistory#component[partitionId,assetId,historySeqNum]{historySeqNum=1, partitionId=272100, assetId=10000721}]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.Cascade [4] [processAutoDecline] - done cascade ACTION_SAVE_UPDATE for collection: com.i21.epay.model.AssetHolder.autopayMemberHistory
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.CascadingAction [4] [processAutoDecline] - cascading to saveOrUpdate: com.i21.epay.model.AssetLock
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.engine.IdentifierValue [4] [processAutoDecline] - id unsaved-value strategy NULL
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.AbstractSaveEventListener [4] [processAutoDecline] - detached instance of: com.i21.epay.model.AssetLock
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating detached instance
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - updating [com.i21.epay.model.AssetLock#10000721]
31 May 2009 20:38:36 DEBUG [WebContainer : 1] org.hibernate.event.def.DefaultSaveOrUpdateEventListener [4] [processAutoDecline] - calling onUpdate()
.......



I am comparatively new to Hibernate, any help is much appreciated.


Top
 Profile  
 
 Post subject: Re: saveOrUpdate() issuing update instead of insert
PostPosted: Tue Jun 02, 2009 1:25 pm 
Newbie

Joined: Mon Jun 01, 2009 7:23 pm
Posts: 2
Ok, there should be one problem which I think I never noticed in migration documents.

The application interceptor which the application can define has the provision of defining custom intercepts for Hibernate. In my code, there is a Interceptor defined in application which is implemented from net.sf.hibernate.Interceptor. The custom class had defined public Boolean isUnsaved(Object entity) method which had its own logic to determine whether to return Boolean.FALSE or Boolean.TRUE. If returned Boolean.FALSE, the call for saveOrUpdate will proceed with Update, else with Save. In my 2.x version of Hibernate, the method was returning Boolean.TRUE hence was issuing save for saveOrUpdate method.

When I migrated the code to 3.3.1, the Interceptor defined for this version does not have a public Boolean isUnsaved(Object entity); method, and its modified to public Boolean isTransient(Object entity); A false from this method indicates that the entity is detached, and hence proceed with update into the database.

I should have updated my application interceptor to modify the public Boolean isUnsaved(Object entity); method to public Boolean isTransient(Object entity); method. Hopefully it should work then (Any thing else I need to take care here? Because a False is a detached assumption here where as a False in 2.x is a update assumption. So would it be safe to assume that this will not have any impact? I mean to assume that the detached always means update or vice versa?)

Also noticed a change in public Object instantiate(Class clazz, Serializable id) throws CallbackException; to public Object instantiate(String entityName, EntityMode entityMode, Serializable id) throws CallbackException. but hopefully it will not create an issue for me since I haven't created a custom override of the same. The method signature, I assume, should be transparent to the migration efforts

Please correct my statements if you feel it does not stand good


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