考虑以下情况 -
有两个表(模式相同),称为ActiveIssue
和ResolvedIssue
。当问题处于活动状态时,它位于ActiveIssue表中,当问题解决后,它将移至ResolvedIssue表。问题可以相互关联。
我有一个方法可以执行以下操作 -
在调用此方法之前,我设置session.setFlushMode(FlushMode.MANUAL)
以避免以下情况 -
但是,我发现即使使用了这个逻辑,我也遇到了WrongClassException。例如,我得到了
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。 会话中的对象不应该一致吗?
答案 0 :(得分:1)
setFlushMode(...)
:刷新是同步的过程 具有持久状态的底层持久存储保存在内存中。
简单来说,它将告诉何时从内存中更新/删除(同步)数据。
如果通过FlushMode
,您将知道将FlushMode设置为MANUAL意味着内存将获得同步。当你说session.flush()
时。
考虑一个场景,其中一个线程正在完成工作,将X问题从ActiveIssue转移到ResolvedIssue,同时另一个线程调用1. Get related issues for an issue from ActiveIssue
因此,在调用此方法之前,您将FlushMode设置为MANUAL,因此它不会同步。在查询执行之前。根据作者
FlushMode.AUTO: 会话有时在查询执行之前刷新,以确保查询永远不会返回失效状态。
因此,当您在表上查询Get related issues for an issue from ActiveIssue
时,某个特定问题X(123456)可能被另一个线程移动到ResolvedIssue。所以id 123456不是ActiveIssue
类型,所以你得到这个异常
答案 1 :(得分:1)
手动刷新模式仅影响当前会话而不影响任何其他竞争线程。由于Transactions,每个线程都在Isolation中运行。当您将实体从一个类型移动到另一个类型时,可能是当前Session保持对给定id的旧类型(例如ActiveIssue)的引用,而您尝试持久化/合并不同类型(例如ResolvedIssue)实体具有相同的ID。
确保您始终删除旧条目,刷新更改(即使在AUTO上),然后为相同的ID添加新类型。