当FlushMode设置为MANUAL时,为什么Hibernate会抛出WrongClassException?

时间:2014-06-24 15:45:46

标签: spring hibernate exception jpa orm

考虑以下情况 -

有两个表(模式相同),称为ActiveIssueResolvedIssue。当问题处于活动状态时,它位于ActiveIssue表中,当问题解决后,它将移至ResolvedIssue表。问题可以相互关联。

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

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

    在调用此方法之前,我设置session.setFlushMode(FlushMode.MANUAL)以避免以下情况 -

    1. 从ActiveIssue获取相关问题
    2. 在后台,问题X得到解决,并从ActiveIssue移至ResolvedIssue
    3. 从ResolvedIssue获取相关问题(由于问题X导致冲突)
    4. 但是,我发现即使使用了这个逻辑,我也遇到了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。 会话中的对象不应该一致吗?

2 个答案:

答案 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添加新类型。