我使用hibernate在基于spring框架的web应用程序控制器中获得了此异常。我曾尝试过许多方法来对付这一问题,但无法解决。
在控制器的方法handleRequestInternal中,对数据库的调用主要是为了“读”,除非它是提交操作。我一直在使用Spring的会话,但是转移到了getHibernateTemplate(),问题仍然存在。
基本上,这是对数据库的第二个调用引发了这个异常。这就是:
1) getEquipmentsByNumber(number) {首先根据'number‘从DB中获取设备,其中有一个属性列表,每个属性都有一个值列表。我循环遍历那些值(原始对象字符串)来读取变量)
2) getMaterialById(id) {基于id}获取材料
我确实理解第二个调用,很可能是使会话“刷新”,但我只是‘读取’对象,那么为什么第二个调用在设备属性上抛出陈旧的对象状态异常(如果没有任何更改)?
调用后无法清除缓存,因为它会导致传递给视图的对象上的LazyExceptions。
我读过这样的文章:https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0,但不能根据所提供的建议来解决问题。
我怎样才能解决这个问题?任何想法和想法都会受到赞赏。
更新:我刚刚测试的是,在函数getEquipmentsByNumber()中,在读取属性列表中的变量之后,我执行以下操作:getHibernateTemplate().flush();,现在异常在这一行上,而不是调用获取材料(即getMaterialById(id))。
更新:在显式调用之前,我要从会话缓存中删除对象,这样缓存中就不会有过时的对象。
getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();好的,在我完成这个操作之后,问题转移到了从DB进行下一个fetch。我想我必须将这些方法标记为同步的,并在读取完对象内容后立即驱逐它们!听起来不太好。
更新:使handleRequestInternal方法“同步”。错误消失了。当然,不是最好的解决方案,而是该怎么做!在handleRequestInternal中尝试关闭当前会话并打开一个新会话。但这会导致应用程序的其他部分不能正常工作。尝试使用不起作用的ThreadLocal。
发布于 2011-11-15 05:18:27
您正在错误地使用Hibernate,这会使它认为您在更新或删除数据库中的对象。
这就是为什么调用flush()会抛出一个异常。
一种可能性:通过servlet或控制器的成员字段,您不正确地“共享”会话或实体。这是“同步”会改变错误症状的主要原因。简短的解决方案:永远不要这样做。会话和实体不应该以这种方式工作--每个请求都应该独立处理。
另一种可能性:对于"int“PK字段,unsaved-value 默认为0。如果您真的想使用0作为有效的PK值,您可能可以将这些输入为"Integer“。
第三个建议:显式地使用Hibernate会话,学习编写简单正确的代码来工作,然后加载Hibernate/ Spring库的Java源代码,这样您就可以阅读和理解这些库实际上为您做了什么。
发布于 2011-09-15 19:56:42
我也一直在与这个异常作斗争,但当它继续出现时,即使我对对象设置了一个锁(在测试环境中,我知道我是唯一接触该对象的进程),我决定适当考虑堆栈跟踪中的括号。
org.hibernate.StaleObjectStateException: Row被另一个事务更新或删除(或未保存的值映射不正确):com.rc.model.mexp.MerchantAccount#59132
在我们的例子中,结果发现映射是错误的;对于数据库中的一个中介文本类型的字段,我们在映射中使用了type="text",而且Hibernate似乎真的讨厌它,至少在某些情况下是如此。我们从该字段的映射中完全删除了类型规范,并解决了这个问题。
奇怪的是,在我们的生产环境中,假设有问题的映射已经到位,我们没有得到这个异常。有人知道为什么会这样吗?我们在开发和生产env中使用相同版本的MySQL -- "5.0.22-log“(我不知道"-log”是什么意思)。
发布于 2010-11-05 07:10:17
这里有3种可能性(正如我不知道的那样,您使用的是哪种hibernate会话)。一个接一个地添加并测试:
在父对象和子对象之间使用inverse=true双向映射,这样父对象或子对象的变化就会正确地传播到关系的另一端。
使用或Version列添加对TimeStamp乐观锁定的支持
使用联接查询一起获取整个对象图parent+children,以避免第二次调用。
最后,如果什么都不起作用的话:通过Id再次加载父数据(已经有了),然后填充修改过的数据,然后进行更新。
生活将是美好的!)
https://stackoverflow.com/questions/3158491
复制相似问题