title: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
body: <p>I have a java project that runs on a webserver. I always hit this exception.</p>
  <p>I read some documentation and found that pessimistic locking (or optimistic, but I read that pessimistic is better) is the best way to prevent this exception.</p>
  <p>But I couldn't find any clear example that explains how to use it.</p>
  <p>My method is like:</p>
  <pre><code>    @Transactional
      public void test(Email email, String subject) {
          getEmailById(String id);
          email.setSubject(subject);
          updateEmail(email);
      }
  </code></pre>
  <p>while:</p>
  <ul>
  <li><code>Email</code> is a Hibernate class (it will be a table in the database)</li>
  <li><code>getEmailById(String id)</code> is a function that returns an <code>email</code> (this method is not annotated with <code>@Transactional</code>)</li>
  <li><code>updateEmail(email)</code>: is a method that updates the email.</li>
  </ul>
  <p><em>Note:</em> I use Hibernate for save, update &amp; so on (example: <code>session.getcurrentSession.save(email)</code>)</p>
  <p><em>The exception:</em></p>
  <pre><code>ERROR 2011-12-21 15:29:24,910 Could not synchronize database state with session [myScheduler-1]
  org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [email#21]
      at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1792)
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2435)
      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)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365)
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
      at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
      at $Proxy130.generateEmail(Unknown Source)
      at com.admtel.appserver.tasks.EmailSender.run(EmailNotificationSender.java:33)
      at com.admtel.appserver.tasks.EmailSender$$FastClassByCGLIB$$ea0d4fc2.invoke(&lt;generated&gt;)
      at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
      at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:50)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
      at com.admtel.appserver.tasks.EmailNotificationSender$$EnhancerByCGLIB$$33eb7303.run(&lt;generated&gt;)
      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.util.MethodInvoker.invoke(MethodInvoker.java:273)
      at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
      at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
      at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
      at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
      at java.lang.Thread.run(Thread.java:680)
  ERROR 2011-12-21 15:29:24,915 [ exception thrown &lt; EmailNotificationSender.run() &gt; exception message Object of class [Email] with identifier [211]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Email#21] with params ] [myScheduler-1]
  org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [Email] with identifier [21]: optimistic locking failed; nested exception is 
  </code></pre>