Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Unexpected update action when deleting entity
PostPosted: Fri Jan 06, 2006 9:19 pm 
Newbie

Joined: Fri Dec 30, 2005 9:19 am
Posts: 3
Location: Buenos Aires
I am working with Hbm 3.0.5 and I can't undestand why Hibernate is performing an UPDATE when flushing the Session when the only action performed by me was a DELETE. I am 99 percent sure I am not modifying the entity or any entity in its graph at all. The most curious thing is that Hbm issues an update without incrementing the version number (im working with optimistic locking with automatic versioning). I 've been debugging hibernate source code for two days and I cannot find the answer to this issue. It seems that dirtyChech() is returning true when it shouldn't. Hbm finds that child collections in my parent entity are dirty and this is not true because no items were added since the entity was retrieved in the active session.

Hibernate version: 3.0.5

Mapping documents:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="ar.com.tgs.spac.domain.solicitud.SolicitudEnHora"
table="SPA_SOLICITUD" schema="SPA">

<!-- Id -->
<composite-id name="id"
class="ar.com.tgs.spac.domain.solicitud.SolicitudId" access="field">
<key-property name="codigoContrato" column="CD_CTRTO" access="field"/>
<key-property name="numeroSolicitud" column="NR_SOLICITUD" access="field"/>
</composite-id>

<!-- Versión -->
<version name="version"
type="long"
access="field"
column="VERSION"
unsaved-value="negative"/>

<!-- Auditoría -->
<property name="fechaUltimaModificacion"
type="timestamp"
column="FE_ULTIMA_MODIF"
not-null="true"/>
<property name="usuarioUltimaModificacion"
type="string"
column="ID_USUARIO_MODIF"
not-null="true"/>

<!-- Properties -->
<property name="estado"
type="ar.com.tgs.spac.repository.usertype.EstadoComprobanteUserType"
access="field"
column="CD_ST_SOLICITUD"/>

<property name="fechaInicial"
type="date"
column="FE_INICIAL_SOLICITUD"
not-null="true"/>

<property name="fechaFinal"
type="date"
column="FE_FINAL_SOLICITUD"
not-null="true"/>

<many-to-one name="contrato"
class="ar.com.tgs.spac.domain.contrato.Contrato"
column="CD_CTRTO"
insert="false"
update="false" access="field"/>

<set name="puntos"
table="SPA_SOLIC_PTO_CARG"
inverse="true"
cascade="all-delete-orphan" lazy="true" access="field">
<key>
<column name="CD_CTRTO"/>
<column name="NR_SOLICITUD"/>
</key>
<one-to-many class="ar.com.tgs.spac.domain.solicitud.PuntoEnSolicitudEnHora"/>
</set>

<set name="caminos"
table="SPA_SOLIC_ZONA_CARG"
cascade="all-delete-orphan"
inverse="true" lazy="true" access="field">
<key>
<column name="CD_CTRTO"/>
<column name="NR_SOLICITUD"/>
</key>
<one-to-many class="ar.com.tgs.spac.domain.solicitud.CaminoEnSolicitudEnHora"/>
</set>


</class>

</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="ar.com.tgs.spac.domain.solicitud.PuntoEnSolicitudEnHora"
table="SPA_SOLIC_PTO_CARG" schema="SPA">

<!-- Id -->
<composite-id name="id"
class="ar.com.tgs.spac.domain.solicitud.PuntoEnSolicitudId">
<key-property name="codigoContrato" column="CD_CTRTO" access="field"/>
<key-property name="numeroPunto" column="NR_PTO" access="field"/>
<key-property name="codigoZona" column="CD_ZONA" access="field"/>
<key-property name="rolPunto" column="ID_ROL_PTO"
type="ar.com.tgs.spac.repository.usertype.RolPuntoUserType" access="field"/>
<key-property name="prioridadPunto" column="PRIOR_PTO" access="field"/>
<key-property name="referenciaAAAA" column="REF_AA_AA" access="field"/>
<key-property name="numeroSolicitud" column="NR_SOLICITUD" access="field"/>
</composite-id>

<!-- Versión -->
<version name="version"
type="long"
access="field"
column="VERSION"
unsaved-value="negative"/>

<!-- Auditoría -->
<property name="fechaUltimaModificacion"
type="timestamp"
column="FE_ULTIMA_MODIF"
not-null="true" access="field"/>

<property name="usuarioUltimaModificacion"
type="string"
column="ID_USUARIO_MODIF"
not-null="true" access="field"/>

<property name="cantidad"
type="long"
column="CA_SOLICITUD_PTO"
not-null="true" access="field"/>

<many-to-one name="solicitud"
class="ar.com.tgs.spac.domain.solicitud.SolicitudEnHora"
insert="false"
update="false" access="field">
<column name="CD_CTRTO"/>
<column name="NR_SOLICITUD"/>
</many-to-one>

<many-to-one name="zona"
class="ar.com.tgs.spac.domain.common.Zona"
insert="false"
update="false" access="field" fetch="select">
<column name="CD_ZONA"/>
</many-to-one>

<many-to-one name="punto"
class="ar.com.tgs.spac.domain.punto.Punto"
column="NR_PTO"
insert="false"
update="false" access="field"/>

</class>

</hibernate-mapping>

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="ar.com.tgs.spac.domain.solicitud.CaminoEnSolicitudFueraDeHora"
table="SPA_EXT_SOLIC_ZONA_CARG" schema="SPA">

<!-- Id -->
<composite-id name="id"
class="ar.com.tgs.spac.domain.solicitud.CaminoEnSolicitudId">
<key-property name="codigoContrato" column="CD_CTRTO" type="string" access="field"/>
<key-property name="numeroSolicitud" column="NR_SOLICITUD" type="long" access="field"/>
<key-property name="codigoZonaRecepcion" column="CD_ZONA_RECEPCION" type="string" access="field"/>
<key-property name="codigoZonaEntrega" column="CD_ZONA_ENTREGA" type="string" access="field"/>
<key-property name="tipoCamino" column="ST_DESBALANCE"
type="ar.com.tgs.spac.repository.usertype.TipoCaminoUserType" access="field"/>
</composite-id>

<!-- Versión -->
<version name="version"
type="long"
access="field"
column="VERSION"
unsaved-value="negative"/>

<!-- Auditoría -->
<property name="fechaUltimaModificacion"
type="timestamp"
column="FE_ULTIMA_MODIF"
not-null="true"/>
<property name="usuarioUltimaModificacion"
type="string"
column="ID_USUARIO_MODIF"
not-null="true"/>

<property name="prioridadRecepcion"
type="integer"
column="PRIOR_RECEPCION"
not-null="true"/>

<property name="cantidadRecepcion"
type="integer"
column="CA_RECEPCION"
not-null="true"/>

<property name="prioridadEntrega"
type="integer"
column="PRIOR_ENTREGA"
not-null="true"/>

<property name="cantidadEntrega"
type="integer"
column="CA_ENTREGA"
not-null="true"/>

<property name="cantidadFuel"
type="integer"
column="CA_FUEL"
not-null="true"/>

<many-to-one name="solicitud"
class="ar.com.tgs.spac.domain.solicitud.SolicitudFueraDeHora"
insert="false"
update="false" access="field">
<column name="CD_CTRTO"/>
<column name="NR_SOLICITUD"/>
</many-to-one>

<many-to-one name="zonaRecepcion"
class="ar.com.tgs.spac.domain.common.Zona"
insert="false"
update="false" access="field" fetch="select">
<column name="CD_ZONA_RECEPCION"/>
</many-to-one>

<many-to-one name="zonaEntrega"
class="ar.com.tgs.spac.domain.common.Zona"
insert="false"
update="false" access="field" fetch="select">
<column name="CD_ZONA_ENTREGA"/>
</many-to-one>

</class>

</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

I use Spring's Hibernate Template in my Dao class.

Object o = getHibernateTemplate().get("className",
aSolicitudId);
getHibernateTemplate().delete(o);

Full stack trace of any exception that occurs:
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [ar.com.tgs.spac.domain.solicitud.SolicitudEnHora#[Contrato:ED004, Numero de Solicitud:304]]; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [ar.com.tgs.spac.domain.solicitud.SolicitudEnHora#[Contrato:ED004, Numero de Solicitud:304]]
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [ar.com.tgs.spac.domain.solicitud.SolicitudEnHora#[Contrato:ED004, Numero de Solicitud:304]]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1634)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2293)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2439)
at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:65)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:227)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:145)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:905)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:345)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)


Name and version of the database you are using: Oracle 9i

The generated SQL (show_sql=true):

Debug level Hibernate log excerpt:
[2006-01-06 22:09:02,586] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Existing version: 0 -> New version: 0
[2006-01-06 22:09:02,586] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
[2006-01-06 22:09:02,586] DEBUG org.hibernate.SQL - update SPA.SPA_SOLICITUD set VERSION=? where CD_CTRTO=? and NR_SOLICITUD=? and VERSION=?
Hibernate: update SPA.SPA_SOLICITUD set VERSION=? where CD_CTRTO=? and NR_SOLICITUD=? and VERSION=?
[2006-01-06 22:09:02,586] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
[2006-01-06 22:09:02,586] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Dehydrating entity: [ar.com.tgs.spac.domain.solicitud.SolicitudEnHora#component[codigoContrato,numeroSolicitud]{numeroSolicitud=304, codigoContrato=ED004}]
[2006-01-06 22:09:02,586] DEBUG org.hibernate.type.LongType - binding '0' to parameter: 1
[2006-01-06 22:09:02,586] DEBUG org.hibernate.type.StringType - binding 'ED004' to parameter: 2
[2006-01-06 22:09:02,586] DEBUG org.hibernate.type.LongType - binding '304' to parameter: 3
[2006-01-06 22:09:02,586] DEBUG org.hibernate.type.LongType - binding '0' to parameter: 4

is there anything wrong with this ?

thanks for your help !

_________________
Gabi Baños
Hexacta Inc.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 11, 2006 5:01 am 
Regular
Regular

Joined: Tue Dec 14, 2004 5:21 am
Posts: 104
Location: india
from the exception stack , i think you have to check if the any other code is modifying the persistent instance .

_________________
sHeRiN
thanks for your ratings ...... :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 11, 2006 5:49 am 
Senior
Senior

Joined: Tue Aug 23, 2005 8:52 am
Posts: 181
Have you implemented equals() and hashcode() on this class? Since you use a composite-id, it would be required to have implementations of equals() and hashcode()

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


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 26, 2006 9:32 am 
Newbie

Joined: Fri Dec 30, 2005 9:19 am
Posts: 3
Location: Buenos Aires
Yes, I implemented equals() and hashCode() judiciously.
I have found a workaround for this issue but firstly let me tell you why this unwanted UPDATE action is causing this error.

The application I am developing is a migration project and the new app is using hbm and spring whereas the old app is all PowerBuilder. I turns out that for a period of time both versions of the apps must run side-by-side using the same database and data model. This imposes some extra-work as u might imagine because of optimistic locking and version columns, among other problems. To solve this problem, we have implemented triggers before update on all tables that could possibly be updated from the old power-builder app, so that version column value is incremented when update statements are fired from the old app. This trigger is always fired when an UPDATE statement is not changing the VERSION column (i am assuming that this kind of updates could never be issued by hbm...am i wrong ?).

so, when hbm fires this unwanted and unexpected UPDATE action my trigger is fired during the same database transaction and version column is incremented and consequently the DELETE action fails because of the clause 'WHERE VERSION = x ' (VERSION now is x + 1).

Still reading ? Ohh..thanks !

My workaround for this problem was:
- Implement a custom FlushEventListener:
MyCustomFlushEventListener extends DefaultFlushEventListener
and override performExecutions like this:
Code:
public class TgsFlushEventListener extends DefaultFlushEventListener {

   /**
    * serial version uid
    */
   private static final long serialVersionUID = -2641082688768377280L;

   /**
    * @see org.hibernate.event.def.AbstractFlushingEventListener#performExecutions(
    * org.hibernate.engine.SessionImplementor)
    */
   protected void performExecutions(SessionImplementor session) {
      ActionQueue queue = session.getActionQueue();
      try {
         Collection updates = (Collection) ReflectionUtils.getField("updates", queue);
         Collection deletions = (Collection) ReflectionUtils.getField("deletions", queue);
         if (updates.size() > 0 && deletions.size() > 0) {
            consolidateActions(updates, deletions);
         }
      } catch (SecurityException e) {
         throw new UnexpectedException(e);
      } catch (RuntimeException e) {
         throw new UnexpectedException(e);
      }
      super.performExecutions(session);   
   }

   /**
    * @param updates
    *          la colección de acciones de update de tipo
    *          @link EntityUpdateAction
    *
    * @param deletions
    *          la colección de acciones de delete de tipo
    *          @link org.hibernate.action.EntityDeleteAction
    */
   private void consolidateActions(Collection updates, Collection deletions) {
      List actionsToRemove = new ArrayList();
      for (Iterator iter = updates.iterator(); iter.hasNext();) {
         EntityUpdateAction uAction = (EntityUpdateAction) iter.next();
         if (noVersionIncrementExistsFor(uAction)) {
            actionsToRemove.add(uAction);
         }
      }
      updates.removeAll(actionsToRemove);
   }
   
   /**
    * @param action una acción de tipo @link EntityUpdateAction
    *
    * @return <code>true</code> si la acción de update no determinó
    *       un incremento en la versión del objeto luego del update
    */
   private boolean noVersionIncrementExistsFor(EntityUpdateAction action) {
      Object lastVersion = ReflectionUtils.getField("lastVersion", action);
      Object nextVersion = ReflectionUtils.getField("nextVersion", action);
      return lastVersion.equals(nextVersion);
   }
   
}

_________________
Gabi Baños
Hexacta Inc.


Top
 Profile  
 
 Post subject: Re: Unexpected update action when deleting entity
PostPosted: Fri Nov 19, 2010 1:51 pm 
Newbie

Joined: Fri Nov 19, 2010 9:16 am
Posts: 1
Hi,

I just faced this error that only happens in production environment. I cannot reproduce it in any other.

Jboss 4.0.3
Spring 2.5.6
Hibernate 3.2
Oracle 10

Does anyone have found out what might be the problem?

Code:
2010-11-11 11:00:14,147 WARN  [org.springframework.remoting.support.RemoteInvocationTraceInterceptor] Processing of HttpInvokerServiceExporter remote call resulted in fatal exception: Documents
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
   at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672)
   at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:95)
   at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:460)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
   at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
   at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
   at $Proxy136.deleteDoc(Unknown Source)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
.
.
.
Caused by: 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:61)
   at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
   at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2520)
   at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2697)
   at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:74)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:146)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
   at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)
   ... 53 more


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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.