【发布时间】:2012-06-29 13:50:20
【问题描述】:
关于设置的一些事实:
- 这是一个基于 Tomcat 的应用程序(尽管问题也出现在 Tomcat 的上下文之外 - JUNIT)
- 不使用 Spring
- 每个线程都有自己的 Hibernate
Session(在 TLS 上) - 对象以混合方式保存/加载,即
ObjA可能由线程A创建,然后由线程B操作,甚至后来由线程 A 更新,然后再次由线程 Z 操作,但这次使用 HQL!
进行上述设置后,我遇到了以下错误:
org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessionsorg.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
我的理解是这样的
- 这都与 Hibernate 的
Session有关,因为会话“拥有”“附加”到它的对象(它创建/加载的对象) - 可能还有缓存问题
问题很明显:
- 我是否了解核心问题(上)?
- 如何避免此类问题?
- 是否有经验法则可以帮助避免这些问题?
- 是否可以使用 Spring 来解决这个问题(请具体说明一下)?
- 是否会在从数据存储中获取每个对象后从
Session中分离它,然后在更新之前将其附加到Session是处理它的理想方式吗?
如果我只使用一个 Session 对象,我当然可以避免所有这些,但这听起来……阻塞(线程方面)。
我确信这些问题很久以前就解决了,只需要找到它(无需重新发明轮子)。
【问题讨论】:
-
第二个异常 (StaleObjectStateException) 如果您有多个线程同时读取和写入同一个数据库实体,则完全有效,例如线程 1 读取对象 A,线程 2 读取对象 A,线程 1 写入对象 A,线程 2(尝试)写入对象 A - 瞧,异常。你的代码应该处理这个。
-
@JonoB 对,我的代码应该处理它,这就是我的问题:) 我该如何处理它?我想我可以想出我自己的方式,但我相信有一些优雅的方式可以让这里的人分享。 如何非常重要。
-
我的第一个建议是阅读乐观锁定。
-
是的,从
StaleObjectStateException中恢复是一回事,但另一个 (....proxy with two open Sessions) 呢?这个是杀手,除非我找到一些经验法则,比如......甚至不知道! -
在问题中看到一些代码会很好;)
标签: java multithreading hibernate session