-->
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.  [ 6 posts ] 
Author Message
 Post subject: persistence problems after transaction rollback
PostPosted: Wed May 04, 2005 4:20 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
Hi,

I am running a test to make sure that my system can recover from a persistence exception. My test scenario is:
    I persist an entity with a mandatory field set to null (in order for the save to fail)
    I catch the exception being thrown
    I populate the missing field
    I re-persist the entity
    I expect the entity to be saved, but I am having an exception.
Code:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
   at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:92)
(please see below for the complete stack trace)

In terms of Transaction management, here it what happens
On first persistence attempt: The transaction is created and rolled back when the error occurs while persisting the null value. Then, the session is cleared.
The object is modified in order not to have any null values and on the second attempt, another transaction is created for saving the updated entity. The transaction rolls back because an exception is thrown by the Batcher.

I have read elswhere that this might be due to batching and that I should try changing the batch update size. I turned it on and off and it makes no difference both the NonBatchingBatcher and the BatchingBatcher throw the same type of exception:
Code:
org.hibernate.HibernateException: Unexpected row count: 0 expected: 1
   at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:32)



Hibernate version:
3.0.2

Mapping documents:
The entity that is being persisted in the test.
Code:
    <class name="SecurityRoleImpl" table="security_role" lazy="true">
        <id name="id" column="id" type="java.lang.Long">
            <generator class="hilo"/>
        </id>
        <property name="name" column="role_name" type="java.lang.String"  not-null="true" />
        <property name="creationDate" column="created" type="java.util.Date"  not-null="true" access="field" />
        <property name="lastModificationDate" column="modified" type="java.util.Date"  not-null="true" access="field" />
        <many-to-one unique="true" name="domain" column="domain_id" class="SecurityDomainImpl" access="field"></many-to-one> 
      <set name="assignedAcls" table="security_role_to_acl" lazy="true" inverse="true"  cascade="save-update" access="field">
            <key column="role_id"/>
            <many-to-many class="SecurityACLImpl" column="acl_id"/>
        </set>
        <filter name="FilterSecurityObjectBasedOnDomainId" condition="domain_id=:domainId"/>
    </class>


Code between sessionFactory.openSession() and session.close():
Please read notes below for variable description.
Code:
private Object processWithTransaction(StandaloneServiceManagerCommand cmd) throws ServiceException, ExistingSecurityObjectException
    {
        boolean exceptionThrown = false;
        Transaction trx = strategy.getSession().beginTransaction();
        try{
            return cmd.execute(entitlementManagementServices);
        }
        --- NOTE ---
        --- A couple of specific exceptions are catched here... ---
        catch(Exception e){
           exceptionThrown = true;
           throw new ServiceException("An unknow exception was thrown while executing a persistence command.", e);
        }
        finally{
            if(exceptionThrown){               
                rollbackTransaction(trx);               
            }else{
                try{
                    commitTransaction(trx);
                }catch(Exception e){
                    rollbackTransaction(trx);
                }
            }
        }
    }

NOTE: strategy is an object that is injected in every object that requires a session. It synchronizes the session to the current thread.
cmd is a command executed by the transaction manager... The command that is executed for a save is roughly: session.save(entity);

Full stack trace of any exception that occurs:
Code:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
   at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:92)
   at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:78)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:57)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:172)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:678)
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.process(AbstractHibernateDAO.java:47)
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.saveOrUpdate(AbstractHibernateDAO.java:109)
   at com.db.eps.common.entitlement.service.persistence.DAO.impl.HibernateSecurityObjectDAO.save(HibernateSecurityObjectDAO.java:44)
   at com.db.eps.common.entitlement.service.facade.pojo.EntitlementManagementServicesImpl.saveRole(EntitlementManagementServicesImpl.java:152)
   at com.db.eps.common.entitlement.service.facade.pojo.StandaloneEntitlementManagementServiceImpl$3.execute(StandaloneEntitlementManagementServiceImpl.java:60)
   at com.db.eps.common.entitlement.service.facade.pojo.StandaloneEntitlementManagementServiceImpl.processWithTransaction(StandaloneEntitlementManagementServiceImpl.java:365)
   at com.db.eps.common.entitlement.service.facade.pojo.StandaloneEntitlementManagementServiceImpl.saveRole(StandaloneEntitlementManagementServiceImpl.java:58)
   at com.db.eps.common.entitlement.service.facade.pojo.StandaloneEntitlementManagementServiceImplTest.testStandaloneEntitlementServiceCanRetrieveDataAfterAWriteFailureForNotNullValue(StandaloneEntitlementManagementServiceImplTest.java:123)


Name and version of the database you are using:
Sybase

The generated SQL (show_sql=true):
Quote:
update security_role set role_name=?, created=?, modified=?, domain_id=? where id=?


Thanks for your help

Vincent Giguère

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 04, 2005 4:27 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
[url]http://www.hibernate.org/hib_docs/v3/reference/en/html/transactions.html#transactions-demarcation-exceptions
[/url]


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 04, 2005 4:57 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
Hi Steeve,

Thanks for referring me to this paragraph. I understand now that I should not try to recover the exception and that I should destroy the session and get another one.

I made these changes to my code and now, the session is destroyed when the transaction rolls back.

The flow is now:
    Create an entity with empty fields
    1. Open a transaction
    2. Persist the entity
    3. Catch the exception
    4. Roll back the transaction
    5. Release the session
    6. Put data in the entity to persist
    7. Create a new session
    8. create a new transaction
    9. persist the entity
    10. commit the transaction


I am still getting the same error when persisting the entity.
PS - I confirm that the session is released between the two attempts.
My JDBC driver is JConnect 6.0

I think it has to do with transactions but I could be making a mistake... but If I try the same test but that I persist an object with no null values at step 2, (In the same as in my test at step 9) everything works fine.

Thanks again

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 05, 2005 12:00 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
Steeve, the is the execution trace of the code that fails. I have debug information about everything related to transaction management and to session management.
You can see that the second attempt at persisting the entity is made with a new instance of a Session obtained through the SessionFactory.

Explanation: There is a class called SessionPerThreadStrategy that synchronizes a Session with a TreadLocal and manages references obtained. When no more references are held, the session is closed and the reference is never used again ( a new session is created upon the next request).

Execution trace:
Code:



//This is when attempting to save the entity at first
//The service aquires a reference to the session in order to start a transaction
2005-05-05 11:55:16,204 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Processing with transaction
2005-05-05 11:55:16,214 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Creating Transaction
2005-05-05 11:55:16,214 DEBUG SessionPerThreadStrategy.getSession - Acquiring session for thread: main
2005-05-05 11:55:16,214 DEBUG SessionPerThreadStrategy.getSession - Session does not exist yet; will create one
2005-05-05 11:55:16,214 DEBUG SessionPerThreadStrategy.createSession - Created an instance of session. Hashcode: 5076660
2005-05-05 11:55:16,214 DEBUG SessionPerThreadStrategy.sessionAcquired - Session was acquired; increasing number of references to: 1
2005-05-05 11:55:16,214 DEBUG SessionPerThreadStrategy.getSession - Returning instance of session with Hashcode: 5076660
2005-05-05 11:55:16,634 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Transaction created
2005-05-05 11:55:16,634 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Executing command
2005-05-05 11:55:16,634 DEBUG EntitlementManagementServicesImpl.saveRole - Saving a SecurityRole. name -> null
//The DAO class gets a reference to the session
2005-05-05 11:55:16,644 DEBUG SessionPerThreadStrategy.getSession - Acquiring session for thread: main
2005-05-05 11:55:16,644 DEBUG SessionPerThreadStrategy.sessionAcquired - Session was acquired; increasing number of references to: 2
2005-05-05 11:55:16,644 DEBUG SessionPerThreadStrategy.getSession - Returning instance of session with Hashcode: 5076660
//The exception is thrown - the DAO releases its reference to the session
2005-05-05 11:55:21,001 DEBUG SessionPerThreadStrategy.releaseSession - Releasing session for thread: main
2005-05-05 11:55:21,001 DEBUG SessionPerThreadStrategy.sessionReleased - Session was released; decreasing number of references to: 1
2005-05-05 11:55:21,001 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - ServiceException Error saving role with name:null
//The service rolls back the transaction
2005-05-05 11:55:21,021 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - TRANSACTION IS BEING ROLLED BACK
//The service rolls releases its reference to the session
2005-05-05 11:55:21,461 DEBUG SessionPerThreadStrategy.releaseSession - Releasing session for thread: main
2005-05-05 11:55:21,461 DEBUG SessionPerThreadStrategy.sessionReleased - Session was released; decreasing number of references to: 0
//The session is closed and no reference to it are held
2005-05-05 11:55:21,461 DEBUG SessionPerThreadStrategy.releaseSession - Session no longer in use; will be closed now
2005-05-05 11:55:21,822 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - TRANSACTION ROLLED BACK
//The entity is fixed (null values are set)
//The service acquires a reference to the session in order to start a transaction
2005-05-05 11:55:21,832 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Processing with transaction
2005-05-05 11:55:21,832 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Creating Transaction
2005-05-05 11:55:21,832 DEBUG SessionPerThreadStrategy.getSession - Acquiring session for thread: main
//A New session is created
2005-05-05 11:55:21,842 DEBUG SessionPerThreadStrategy.getSession - Session does not exist yet; will create one
2005-05-05 11:55:21,842 DEBUG SessionPerThreadStrategy.createSession - Created an instance of session. Hashcode: 29071960
2005-05-05 11:55:21,842 DEBUG SessionPerThreadStrategy.sessionAcquired - Session was acquired; increasing number of references to: 1
2005-05-05 11:55:21,842 DEBUG SessionPerThreadStrategy.getSession - Returning instance of session with Hashcode: 29071960
2005-05-05 11:55:22,603 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Transaction created
2005-05-05 11:55:22,603 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - Executing command
2005-05-05 11:55:22,613 DEBUG EntitlementManagementServicesImpl.saveRole - Saving a SecurityRole. name -> FailureTestRole1115308521832
//The DAO class gets a reference to the session
2005-05-05 11:55:22,613 DEBUG SessionPerThreadStrategy.getSession - Acquiring session for thread: main
2005-05-05 11:55:22,613 DEBUG SessionPerThreadStrategy.sessionAcquired - Session was acquired; increasing number of references to: 2
2005-05-05 11:55:22,613 DEBUG SessionPerThreadStrategy.getSession - Returning instance of session with Hashcode: 29071960
Hibernate: update security_role set role_name=?, created=?, modified=?, domain_id=? where id=?
//An exception is throw. The DAO releases its reference (this exception should not occur)
2005-05-05 11:55:22,973 DEBUG SessionPerThreadStrategy.releaseSession - Releasing session for thread: main
2005-05-05 11:55:22,973 DEBUG SessionPerThreadStrategy.sessionReleased - Session was released; decreasing number of references to: 1
//The services catches the exception and rolls back the transaction
2005-05-05 11:55:22,973 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - ServiceException Error saving role with name:FailureTestRole1115308521832
2005-05-05 11:55:22,984 DEBUG StandaloneEntitlementManagementServiceImpl.processWithTransaction - TRANSACTION IS BEING ROLLED BACK
//The service releases its session
2005-05-05 11:55:23,334 DEBUG SessionPerThreadStrategy.releaseSession - Releasing session for thread: main
2005-05-05 11:55:23,344 DEBUG SessionPerThreadStrategy.sessionReleased - Session was released; decreasing number of references to: 0
2005-05-05 11:55:23,344 DEBUG SessionPerThreadStrategy.releaseSession - Session no longer in use; will be closed now


And then the exception is throw which wraps the following:
Code:
Caused by: com.db.eps.common.persistence.DataAccessException: org.hibernate.HibernateException: Unexpected row count: 0 expected: 1
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.convertToDataAccessException(AbstractHibernateDAO.java:69)
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.process(AbstractHibernateDAO.java:51)
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.saveOrUpdate(AbstractHibernateDAO.java:109)
   at com.db.eps.common.entitlement.service.persistence.DAO.impl.HibernateSecurityObjectDAO.save(HibernateSecurityObjectDAO.java:44)
   at com.db.eps.common.entitlement.service.facade.pojo.EntitlementManagementServicesImpl.saveRole(EntitlementManagementServicesImpl.java:142)


Thanks in advance for your help.

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 05, 2005 12:02 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
I am sorry... the stack trace from the previous message should be:

Code:
Caused by: org.hibernate.HibernateException: Unexpected row count: 0 expected: 1
   at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:32)
   at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:1972)
   at org.hibernate.persister.entity.BasicEntityPersister.updateOrInsert(BasicEntityPersister.java:1899)
   at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2139)
   at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:75)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:678)
   at com.db.eps.common.persistence.hibernate.support.AbstractHibernateDAO.process(AbstractHibernateDAO.java:47)

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 13, 2005 6:45 pm 
Expert
Expert

Joined: Thu Jan 08, 2004 6:17 pm
Posts: 278
Here is a relevant thread (to which I am trying to unify many other threads on this topic):

Related thread here.


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