在我的代码中,我将数据保存到Microsoft SQL数据库版本10.50.4042.0 我正在使用hibernate-validator版本4.2.0.CR1和hibernate-commons-annotations版本3.2.0.Final
我正在研究由Maven构建的几个连接在Spring框架上的项目。在我的测试项目中(使用junit 4.8.2)我试图通过选择几个xml文件并将它们转换为数据库行来将数据保存到数据库中(一次一行)。在我处理SQL事务的项目中,我使用这个注释将数据发送到数据库
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
我认为问题发生在hibernate的Transactional过程中。但是没有异步调用,XML结构完全有效。我尝试了不同的方法,但问题似乎非常随机地发生,没有任何特定的模式,它无法只保存1个随机数据行。
我得到的错误信息是:
2016-06-09 12:41:01,578: ERROR [http-8080-Processor3] Could not synchronize database state with session
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:2574)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2478)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2805)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:114)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:260)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:180)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
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 com.sun.proxy.$Proxy48.save(Unknown Source)
没有其他SQL调用同时更新行。 如果你在hibernate中遇到同样的问题,你能帮忙吗?或者任何其他建议可能会有所帮助。 谢谢
答案 0 :(得分:2)
实际上这个问题意味着
无法找到您指定ID的记录。
为了避免这种情况,我总是读取具有相同id的记录,如果我找回记录,那么我会调用update,否则抛出"exception record not found"
。
您删除了一个对象,然后尝试更新它。在这种情况下,您需要清除会话session.clear();
在id
属性的Hibernate映射文件中,如果使用任何生成器类,则对于该属性,不应使用setter方法显式设置该值。
如果明确设置Id属性的值,则会导致上述错误。选中此项以避免此错误。
但是,为了更好地处理导致问题的原因,请尝试以下方法:
set hibernate.show_sql to true
。
这应该显示执行的SQL并导致
问题。log levels for Spring and Hibernate to DEBUG
会让你更好地了解哪一行会导致问题。此异常将出现在hibernate的save和saveOrupdate方法的不同场景中。
如果Object是瞬态的,需要保存可能会发生此异常 条件。
对象不存在:这是最容易确定的:是否以某种方式删除了对象?如果是这样,尝试再次删除它将抛出此异常。
对象陈旧: Hibernate从会话中缓存对象。如果对象被修改,并且Hibernate不知道它,它将抛出此异常 - 请注意异常的StaleStateException
部分。
所以在将对象提交到数据库后需要flush
或clear
或clean
,而不是之前。
答案 1 :(得分:1)
据我所知,可能存在以下三个原因之一:
如果上述三个问题都不能解决您的问题,请分享您的代码。
答案 2 :(得分:1)
在阅读你的解释时,我觉得这也是与你的交易隔离程度相关的问题。
READ_COMMITTED隔离级别指定只能访问未在开放事务中理解的记录,因此我认为在您的情况下,随机发生另一个事务访问您的一个或多个记录批量更新,因此它引发了异常。
我认为一个解决方案是,每次按行提交一个提交,每次都验证行的db状态,或者相反,您可以管理此异常,以避免停止进程或事务。