Wes
Wes

Reputation: 904

Why would Hibernate throw a WrongClassException when the FlushMode is set to MANUAL?

Consider the following scenario -

There are two tables (identical in schema) called ActiveIssue and ResolvedIssue. When an issue is active, it is in the ActiveIssue table and when the issue is resolved, it is moved to the ResolvedIssue table. Issues can be related to each other.

I have a method that does the following -

  1. Get related issues for an issue from ActiveIssue
  2. Get related issues for an issue from ResolvedIssue

Before calling this method, I set session.setFlushMode(FlushMode.MANUAL) to avoid the following scenario -

  1. Get related issues from ActiveIssue
  2. In the background, an issue X gets resolved and moves from ActiveIssue to ResolvedIssue
  3. Get related issues from ResolvedIssue (leads to conflict because of issue X)

However, I observe that I run into a WrongClassException even with this logic in place. For instance, I get

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

I am using org.springframework.orm.hibernate3.support.HibernateDaoSupport and I call Session session = getSession() on this object. ActiveIssue and ResolvedIssue both derive from a base class called Issue. I use the InheritanceType.TABLE_PER_CLASS inheritance strategy on the base class, so ActiveIssue is mapped to the ActiveIssue table and ResolvedIssue is mapped to the ResolvedIssue table.

I don't understand why the WrongClassException occurs when I have explicitly set the FlushMode to MANUAL. Shouldn't the objects in the session be consistent?

Upvotes: 0

Views: 164

Answers (2)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 153780

The manual flush mode only affects your current session not any other competing thread. Every thread runs in Isolation thanks to Transactions. When you move an entity from a type to the other, it may be that the current Session holds a reference to the old type(e.g. ActiveIssue ) for a given id, while you try to persist/merge a different type(e.g. ResolvedIssue) entity with the same id.

make sure you always delete the old entry, flush the changes (even on AUTO) and then add the new type for the same id.

Upvotes: 1

Amogh
Amogh

Reputation: 4573

setFlushMode(...) : Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory.

In simple it will tell when to update/remove (sync.) data from memory which is taken from DB.

If go through FlushMode you will come to knwo that setting FlushMode to MANUAL means memory will get sync. when you say session.flush().

Consider an scenario where One thread doing the work shifting an X issue from ActiveIssue to ResolvedIssue and at the same time another thread calling 1. Get related issues for an issue from ActiveIssue

So as per you before calling this you are setting FlushMode to MANUAL so it will not get sync. before query execution. AS per author

FlushMode.AUTO : The Session is sometimes flushed before query execution in order to ensure that queries never return stale state.

So when you query on table to Get related issues for an issue from ActiveIssue an particular issue X (123456) is may be moved to ResolvedIssue by another thread. so the id 123456 is not of type ActiveIssue so that your getting this exception

Upvotes: 1

Related Questions