StaleObjectstateException 行已更新或删除

发布于 2024-09-08 00:43:46 字数 1463 浏览 2 评论 0原文

我在使用 hibernate 的基于 spring 框架的 Web 应用程序的控制器中遇到此异常。我尝试了很多方法来应对这个问题,但无法解决。

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

基本上,对数据库的第二次调用会抛出此异常。即:

1) getEquipmentsByNumber(number) { 首先根据“number”从数据库中获取设备,该设备有一个属性列表,每个属性都有一个值列表。我循环遍历这些值(原始对象字符串)以读入变量)

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

我确实明白第二个调用很可能是进行会话“刷新”,但我只是“读取”对象,那么如果没有任何更改,为什么第二个调用会在 Equipment 属性上引发陈旧对象状态异常?

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

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

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

更新: 我刚刚测试的是,在从属性列表中读取变量后,在函数 getEquipmentsByNumber() 中,我执行以下操作: getHibernateTemplate().flush(); 现在异常发生在这一行,而不是获取材料的调用(即 getMaterialById(id))。

更新: 在显式调用刷新之前,我将从会话缓存中删除该对象,以便缓存中不保留任何过时的对象。

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

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

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

I am getting this exception in a controller of a web application based on spring framework using hibernate. I have tried many ways to counter this but could not resolve it.

In the controller's method, handleRequestInternal, there are calls made to the database mainly for 'read', unless its a submit action.
I have been using, Spring's Session but moved to getHibernateTemplate() and the problem still remains.

basically, this the second call to the database throws this exception. That is:

1) getEquipmentsByNumber(number) { firstly an equipment is fetched from the DB based on the 'number', which has a list of properties and each property has a list of values. I loop through those values (primitive objects Strings) to read in to variables)

2) getMaterialById(id) {fetches materials based on id}

I do understand that the second call, most probably, is making the session to "flush", but I am only 'reading' objects, then why does the second call throws the stale object state exception on the Equipment property if there is nothing changed?

I cannot clear the cache after the call since it causes LazyExceptions on objects that I pass to the view.

I have read this:
https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0
but could not solve the problem based on the suggestions provided.

How can I solve this issue? Any ideas and thoughts are appreciated.

UPDATE:
What I just tested is that in the function getEquipmentsByNumber() after reading the variables from list of properties, I do this: getHibernateTemplate().flush(); and now the exception is on this line rather then the call to fetch material (that is getMaterialById(id)).

UPDATE:
Before explicitly calling flush, I am removing the object from session cache so that no stale object remains in the cache.

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

OK, so now the problem has moved to the next fetch from DB after I did this. I suppose I have to label the methods as synchronized and evict the Objects as soon as I am finished reading their contents! it doesn't sound very good.

UPDATE:
Made the handleRequestInternal method "synchronized". The error disappeared. Ofcourse, not the best solution, but what to do!
Tried in handleRequestInternal to close the current session and open a new one. But it would cause other parts of the app not to work properly. Tried to use ThreadLocal that did not work either.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浪菊怪哟 2024-09-15 00:43:46

您以某种方式错误地使用了 Hibernate,导致它认为您正在从数据库中更新删除对象。

这就是为什么调用flush()会抛出异常。

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

另一种可能性:“int”PK 字段的unsaved-value 默认为 0。如果您确实想使用 0 作为有效的 PK 值,您可以将它们键入为“Integer”。

第三个建议:显式使用 Hibernate Session,学习编写有效的简单正确代码,然后加载 Hibernate/Spring 库的 Java 源代码,以便您可以阅读和使用 Hibernate Session。了解这些库实际上为您做了什么。

You're mis-using Hibernate in some way that causes it to think you're updating or deleting objects from the database.

That's why calling flush() is throwing an exception.

One possibility: you're incorrectly "sharing" Session or Entities, via member field(s) of your servlet or controller. This is the main reason 'synchronized' would change your error symptoms.. Short solution: don't ever do this. Sessions and Entities shouldn't & don't work this way -- each Request should get processed independently.

Another possibility: unsaved-value defaults to 0 for "int" PK fields. You may be able to type these as "Integer" instead, if you really want to use 0 as a valid PK value.

Third suggestion: use Hibernate Session explicitly, learn to write simple correct code that works, then load the Java source for Hibernate/ Spring libraries so you can read & understand what these libraries are actually doing for you.

眼角的笑意。 2024-09-15 00:43:46

我也一直在努力解决这个异常,但是当它继续重复出现时,即使我在对象上加了锁(并且在测试环境中,我知道我是唯一接触该对象的进程),我决定给出括号在堆栈跟踪中应适当考虑。

org.hibernate.StaleObjectStateException:行已更新或删除
另一笔交易(或未保存值映射不正确):
[com.rc.model.mexp.MerchantAccount#59132]

在我们的例子中,事实证明映射是错误的;我们在数据库中一个中等文本类型的字段的映射中使用了 type="text" ,而且 Hibernate 似乎非常讨厌这种情况,至少在某些情况下是这样。我们从该字段的映射中完全删除了类型规范,问题得到了解决。

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

I also have been struggling with this exception, but when it continued to recur even when I put a lock on the object (and in a test environment, where I knew I was the only process touching the object), I decided to give the parenthetical in the stack trace its due consideration.

org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect):
[com.rc.model.mexp.MerchantAccount#59132]

In our case it turned out that the mapping was wrong; we had type="text" in the mapping for one field that was a mediumtext type in the database, and it seems that Hibernate really hates that, at least under certain circumstances. We removed the type specification altogether from the mapping for this field, and the problem was resolved.

Now the weird thing is that in our production environment, with the supposedly problematic mapping in place, we do NOT get this exception. Does anybody have any idea why this might be? We are using the same version of MySQL - "5.0.22-log" (I don't know what the "-log" means) - in dev and production envs.

极致的悲 2024-09-15 00:43:46

这里有 3 种可能性(因为我不确切知道您正在使用哪种休眠会话处理)。逐个添加并测试:

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

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

使用连接查询获取整个对象图 [parent+孩子们]在一起以避免第二次呼叫。

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

生活将会美好! :)

Here are 3 possibilities (as I do not know exactly, which kind of hibernate session handling you are using). Add one after another and test:

Use bi-directional mapping with inverse=true between parent object and child object, so the change in parent or child will get propagate to the other end of relation properly.

Add support for Optimistic Locking using TimeStamp or Version column

Use join query to fetch the whole object graph [ parent+children] together to avoid the second call altogether.

Lastly, if and only if nothing works:
Load the parent again by Id (you have that already) and populate modified data then update.

Life will be good! :)

风柔一江水 2024-09-15 00:43:46

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

首先,确保所有方法都用 @Transaction(required=true) // 您必须查找确切的语法进行注释

但是,当您尝试进行更改时,通常会引发此异常已从检索它的会话中分离的对象。解决这个问题的方法通常并不简单,需要发布更多代码,以便我们能够准确地看到发生了什么;我的一般建议是创建一个 @Service 在单个事务中执行这些类型的事情

This problem was something that I had experienced and was quite frustrating, although there has to be something a little odd going on in your DAO/Hibernate calls, because if you're doing a lookup by ID there is no reason to get a stale state, since that is just a simple lookup for an object.

First, make sure all your methods are annotated with @Transaction(required=true) // you'll have to look up the exact syntax

However, this exception is usually thrown when you try to make changes to an object that has been detached from the session it was retrieved from. The solution to this is often not simple and would require more code posted so we can see exactly what is going on; my general suggestion would be to create a @Service that performs these kinds of things within a single transaction

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文