I am playing with a standard optimistic concurrency control scenario with extended session / automatic versioning. I have an entity which I load in the first transaction, present to user for modification and save in the second one, both transactions sharing the same session. After the entity is somehow modified session.flush() at the end of the second transaction may throw a StaleObjectStateException in case a version inconsistency is detected meaning that a concurrent transaction has saved a next version of the entity in between.
I want to handle such an error in a most simple way — just to reload entity losing current changes and continue with editing and saving again. First I tried this:
session.refresh(entity);
but after I modify and attempt to save this refreshed entity, I still get the same StaleObjectStateException, even though it does get refreshed and the version number appears consistent; yes I know that using refresh() in extended sessions is discouraged, but don’t understand why. Is this behavior related to the reason it is discouraged?
Next I tried the following way to avoid using session.refresh():
session.evict(entity);
entity = session.load(MyEntity.class, id);
but it still results in StaleObjectStateException being raised at saving the entity which is not indeed stale.
The only way I managed to cope with the exception is this:
session.clear();
entity = session.load(MyEntity.class, id);
but isn’t session.clear() the same as session.evict() pertaining to my concrete entity?
To resume, my questions are:
- Why is
StaleObjectStateExceptionstill thrown on a reloaded entity unlesssession.clear()is done? - What is the correct way to reload an entity which has already been loaded in the same session and why is
refresh()bad? Is there something wrong with this approach to implement conversation?
I’m using Hibernate 4.1.7.Final, with no second-level cache.
My apologies if my question is repeating, but I fail to find a profound explanation…
When you get an exception in a session, than that session instance is broken. You cannot use that instance any more and you have to throw it away and create a new instance. The exception is not reset (as you can see you get the same exception again thought logically this should not happen). This is a general rule for using hibernate sessions. The reason for this is, hibernate does not always see why an exception appears and the state of the session instance may be inconsistent.
I don’t know why it works after clear(). This may be accidentally. It is more prudent to use a new instance.
If you use a StatelessSession, then you don’t have this restriction, but stateless sessions have other disadvantages, for example no caching.