StaleObjectstateException行已更新或删除

我在使用hibernate的基于spring框架的Web应用程序的控制器中获得此exception。 我已经尝试了很多方法来解决这个问题,但无法解决它。

在控制器的方法handleRequestInternal ,对数据库进行的调用主要是为了“读取”,除非它是一个提交动作。 我一直在使用,Spring的Session但是转移到getHibernateTemplate()并且问题仍然存在。

基本上,这是对数据库的第二次调用抛出此exception。 那是:

1) getEquipmentsByNumber(number) {首先,根据’number’从DB中提取设备,其中包含属性列表,每个属性都有一个值列表。 我遍历这些值(原始对象字符串)以读入变量)

2) getMaterialById(id) {基于id获取材料}

我确实理解第二次调用很可能是使会话“刷新”,但我只是“读取”对象,那么为什么第二次调用会在Equipment属性上抛出过时的对象状态exception,如果没有任何改变的话?

我无法在调用后清除缓存,因为它会导致我传递给视图的对象上的LazyExceptions。

我已经读过这个: https : //forums.hibernate.org/viewtopic.php?f = 1&t = 996355&start = 0但根据提供的建议无法解决问题。

我该如何解决这个问题? 任何想法和想法都表示赞赏。

更新:我刚刚测试的是,在从属性列表中读取变量之后,在函数getEquipmentsByNumber() ,我这样做: getHibernateTemplate().flush(); 现在exception就在这一行而不是调用fetch材料(即getMaterialById(id) )。

更新:在显式调用flush之前,我从会话缓存中删除对象,以便缓存中没有过时的对象。

 getHibernateTemplate().evict(equipment); getHibernateTemplate().flush(); 

好的,现在问题已经转移到我执行此操作后从DB中的下一次提取。 我想我必须将这些方法标记为已同步,并在我阅读完内容后立即逐出对象! 听起来不太好。

更新:使handleRequestInternal方法“同步”。 错误消失了。 当然,不是最好的解决方案,而是做什么! 试着在handleRequestInternal中关闭当前会话并打开一个新会话。 但它会导致应用程序的其他部分无法正常工作。 试图使用不起作用的ThreadLocal

您以某种方式误用Hibernate会导致它认为您正在更新删除数据库中的对象。

这就是调用flush()抛出exception的原因。

一种可能性: 您通过servlet或控制器的成员字段错误地“共享”会话或实体 。 这是’同步’会改变你的错误症状的主要原因。简短的解决方案:不要这样做。 会话和实体不应该以这种方式工作 – 每个请求都应该独立处理。

另一种可能性: 对于“int”PK字段, unsaved-value默认为0 。 如果你真的想使用0作为有效的PK值,你可以将它们键入为“整数”。

第三个建议: 明确使用Hibernate Session,学习编写简单正确的代码 ,然后加载Hibernate / Spring库的Java源码,这样你就可以阅读并理解这些库实际上为你做了些什么。

我也一直在努力解决这个exception问题,但是当它对物体进行锁定时(即在测试环境中,我知道我是唯一接触物体的过程),当它继续复发时,我决定给出括号在堆栈中追踪其应有的考虑。

org.hibernate.StaleObjectStateException:行被另一个事务更新或删除(或unsaved-value映射不正确):[com.rc.model.mexp.MerchantAccount#59132]

在我们的例子中,事实certificate映射是错误的; 我们在数据库中作为中间type="text"的一个字段的映射中有type="text" ,而且似乎Hibernate真的很讨厌这种情况,至少在某些情况下。 我们从该字段的映射中完全删除了类型规范,问题得到了解决。

现在奇怪的是,在我们的生产环境中,假设有问题的映射,我们不会得到这个例外。 有没有人知道为什么会这样? 我们使用相同版本的MySQL – “5.0.22-log”(我不知道“-log”的意思) – 在开发和生产环境中。

这里有3种可能性(因为我不确切知道,你正在使用哪种hibernate会话处理)。 一个接一个地添加并测试:

在父对象和子对象之间使用inverse=true双向映射,因此父或子的更改将正确地传播到关系的另一端。

使用TimeStampVersion列添加对乐观锁定的支持

使用连接查询一起获取整个对象图[parent + children]以完全避免第二次调用。

最后,当且仅当没有任何作用时:再次通过Id加载父级(您已经拥有)并填充已修改的数据然后更新。

生活会很美好! 🙂

这个问题是我经历过的并且非常令人沮丧,尽管在你的DAO / Hibernate调用中必须有一些奇怪的事情,因为如果你通过ID进行查找,就没有理由得到陈旧状态因为这只是对象的简单查找。

首先,确保所有方法都使用@Transaction(required=true) // you'll have to look up the exact syntax注释@Transaction(required=true) // you'll have to look up the exact syntax

但是,当您尝试更改已从其检索的会话中分离的对象时,通常会抛出此exception。 对此的解决方案通常并不简单,需要发布更多代码,以便我们可以准确地看到正在发生的事情; 我的一般建议是创建一个在单个事务中执行这些事情的@Service