【问题标题】:Why would Hibernate throw a WrongClassException when the FlushMode is set to MANUAL?当 FlushMode 设置为 MANUAL 时,为什么 Hibernate 会抛出 WrongClassException?
【发布时间】:2014-08-14 23:21:22
【问题描述】:

考虑以下场景 -

有两个表(架构相同)称为ActiveIssueResolvedIssue。当问题处于活动状态时,它位于 ActiveIssue 表中,当问题得到解决时,它被移动到 ResolvedIssue 表中。问题可以相互关联。

我有一个方法可以执行以下操作 -

  1. 从 ActiveIssue 获取问题的相关问题
  2. 从 ResolvedIssue 获取问题的相关问题

在调用这个方法之前,我设置了session.setFlushMode(FlushMode.MANUAL)来避免下面的情况——

  1. 从 ActiveIssue 获取相关问题
  2. 在后台,问题 X 得到解决并从 ActiveIssue 移动到 ResolvedIssue
  3. 从 ResolvedIssue 获取相关问题(由于问题 X 导致冲突)

但是,我观察到即使使用此逻辑,我也会遇到 WrongClassException。例如,我得到 ​​p>

org.hibernate.WrongClassException: Object with id: 123456 was not of the 
specified subclass ... ActiveIssue 
(loaded object was of wrong class ... ResolvedIssue)

我正在使用org.springframework.orm.hibernate3.support.HibernateDaoSupport 并在此对象上调用Session session = getSession()。 ActiveIssue 和 ResolvedIssue 都派生自一个名为 Issue 的基类。我在基类上使用InheritanceType.TABLE_PER_CLASS继承策略,所以ActiveIssue映射到ActiveIssue表,ResolvedIssue映射到ResolvedIssue表。

当我将 FlushMode 显式设置为 MANUAL 时,我不明白为什么会出现 WrongClassException。 会话中的对象不应该是一致的吗?

【问题讨论】:

  • 请全栈跟踪!!

标签: spring hibernate exception jpa orm


【解决方案1】:

手动刷新模式只会影响您当前的会话,不会影响任何其他竞争线程。多亏了事务,每个线程都在隔离中运行。当您将实体从一种类型移动到另一种类型时,可能是当前 Session 持有对给定 id 的旧类型(例如 ActiveIssue )的引用,而您尝试保留/合并不同类型(例如 ResolvedIssue)实体具有相同的ID。

确保您始终删除旧条目,刷新更改(即使在 AUTO 上),然后为相同的 id 添加新类型。

【讨论】:

  • 删除旧条目是什么意思?另一个线程已经从数据库中删除了该条目并将其移动到新表中。如果会话持有对旧对象的引用,我该如何删除这些引用?
  • 如果其他线程将其删除,您将得到一个乐观锁定异常。
【解决方案2】:

setFlushMode(...) : 刷新是同步的过程 具有持久状态的底层持久存储在内存中。

简单来说,它会告诉何时从数据库中获取的内存中更新/删除(同步)数据。

如果通过FlushMode,您会知道将 FlushMode 设置为 MANUAL 意味着内存将同步。当你说session.flush()

考虑一个场景,一个线程将 X 问题从 ActiveIssue 转移到 ResolvedIssue,同时另一个线程调用 1. Get related issues for an issue from ActiveIssue

因此,在调用此之前,您将 FlushMode 设置为 MANUAL,这样它就不会同步。在查询执行之前。按作者身份

FlushMode.AUTO: Session 有时会在查询执行之前被刷新,以确保查询永远不会返回过时状态。

因此,当您在表上查询Get related issues for an issue from ActiveIssue 时,特定问题 X (123456) 可能会被另一个线程移动到 ResolvedIssue。所以 id 123456 不是ActiveIssue 类型,所以你得到这个异常

【讨论】:

  • 您为什么使用 FlushMode.MANUAL 处理跨国数据?
  • 我同意这个答案。根据 Hibernate FlushMode.MANUAL 在只读数据中提高性能很有用。这种模式对于只读事务非常有效。
猜你喜欢
  • 2014-09-25
  • 1970-01-01
  • 2012-05-26
  • 2011-04-06
  • 1970-01-01
  • 2011-05-26
  • 2012-11-19
  • 2014-08-17
  • 1970-01-01
相关资源
最近更新 更多