行被另一个事务更新或删除(或未保存的值映射不正确)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了行被另一个事务更新或删除(或未保存的值映射不正确)相关的知识,希望对你有一定的参考价值。
我有一个在Web服务器上运行的java项目。我总是遇到这个例外。
我阅读了一些文档,发现悲观锁定(或乐观,但我认为悲观更好)是防止此异常的最佳方法。
但我找不到任何解释如何使用它的明确例子。
我的方法是这样的:
@Transactional
Public void test(Email email, String Subject){
getEmailById(String id);
email.setSubject(Subject);
updateEmail(email);
}
而:
Email
是一个hibernate类(它将是数据库中的一个表)getEmailById(String id)
是一个返回email
的函数(此方法未使用@Transctional
注释)updateEmail(email)
:是一种更新电子邮件的方法。
注意:我使用hibernate进行保存,更新等等(例如:qazxsw poi)
例外:
session.getcurrentSession.save(email)
通常不建议使用悲观锁定,并且在数据库方面的性能方面非常昂贵。您提到的问题(代码部分)有些事情并不清楚,例如:
- 如果您的代码同时被多个线程访问。
- 你是如何创建
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(<generated>) 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(<generated>) 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 < EmailNotificationSender.run() > 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
对象的(不确定你是否使用Spring)?
Hibernate session
。因此,如果有多个线程访问同一个会话并尝试更新同一个数据库实体,那么您的代码可能最终会出现这样的错误情况。
所以这里发生的是多个线程尝试更新同一个实体,一个线程成功,当下一个线程提交数据时,它看到它已被修改并最终抛出Session objects are NOT thread-safe。
编辑:
有一种方法可以在Hibernate中使用悲观锁定。看看StaleObjectStateException
。但这种机制似乎存在一些问题。然而,我遇到了在hibernate(this link)中发布的错误。 bug中提到的场景如下:
两个线程正在读取相同的数据库记录;其中一个线程应使用悲观锁定,从而阻止其他线程。但是两个线程都可以读取数据库记录,导致测试失败。
这非常接近您面临的情况。请尝试这个,如果这不起作用,我能想到的唯一方法是使用HHH-5275,你可以用Native SQL queries查询实现pessimistic locking in postgres数据库。
以防万一有人检查过这个帖子并且遇到与我相同的问题......
行被另一个事务更新或删除(或未保存的值映射不正确)
我正在使用NHibernate,在创建对象时收到同样的错误...
我手动传递了密钥,并且还在映射中指定了GUID生成器,因此hibernate为我生成了相同的错误,所以一旦我删除了GUID,并将字段留空,一切都很顺利。
这个答案可能对你没有帮助,但会帮助像我这样的人,因为同样的错误也是你的主线
在创建新行后尝试更新现有行时,我也遇到了这个错误,并花了很多时间摸索我的头脑,挖掘事务和版本逻辑,直到我意识到我使用了错误的类型为我的主键列之一。
当我应该使用@Transactional
时,我使用LocalDate
- 我认为这导致hibernate无法区分实体,导致此错误。
将密钥更改为LocalDateTime
后,错误就消失了。此外,更新单个行也开始工作 - 以前它将无法找到更新行,并且测试这个单独的问题实际上是导致我得出关于主键映射的结论的原因。
我的grails项目中遇到了同样的问题。 Bug是,我覆盖了集合字段的getter方法。这
以上是关于行被另一个事务更新或删除(或未保存的值映射不正确)的主要内容,如果未能解决你的问题,请参考以下文章
StaleObjectStateException:行已被另一个事务更新或删除?