StaleObjectstateException row was updated or deleted by

Saky picture Saky · Jul 1, 2010 · Viewed 48.5k times · Source

I am getting this exception in a controller of a web application based on spring framework using hibernate. I have tried many ways to counter this but could not resolve it.

In the controller's method, handleRequestInternal, there are calls made to the database mainly for 'read', unless its a submit action. I have been using, Spring's Session but moved to getHibernateTemplate() and the problem still remains.

basically, this the second call to the database throws this exception. That is:

1) getEquipmentsByNumber(number) { firstly an equipment is fetched from the DB based on the 'number', which has a list of properties and each property has a list of values. I loop through those values (primitive objects Strings) to read in to variables)

2) getMaterialById(id) {fetches materials based on id}

I do understand that the second call, most probably, is making the session to "flush", but I am only 'reading' objects, then why does the second call throws the stale object state exception on the Equipment property if there is nothing changed?

I cannot clear the cache after the call since it causes LazyExceptions on objects that I pass to the view.

I have read this: https://forums.hibernate.org/viewtopic.php?f=1&t=996355&start=0 but could not solve the problem based on the suggestions provided.

How can I solve this issue? Any ideas and thoughts are appreciated.

UPDATE: What I just tested is that in the function getEquipmentsByNumber() after reading the variables from list of properties, I do this: getHibernateTemplate().flush(); and now the exception is on this line rather then the call to fetch material (that is getMaterialById(id)).

UPDATE: Before explicitly calling flush, I am removing the object from session cache so that no stale object remains in the cache.

getHibernateTemplate().evict(equipment);
getHibernateTemplate().flush();

OK, so now the problem has moved to the next fetch from DB after I did this. I suppose I have to label the methods as synchronized and evict the Objects as soon as I am finished reading their contents! it doesn't sound very good.

UPDATE: Made the handleRequestInternal method "synchronized". The error disappeared. Ofcourse, not the best solution, but what to do! Tried in handleRequestInternal to close the current session and open a new one. But it would cause other parts of the app not to work properly. Tried to use ThreadLocal that did not work either.

Answer

Thomas W picture Thomas W · Nov 15, 2011

You're mis-using Hibernate in some way that causes it to think you're updating or deleting objects from the database.

That's why calling flush() is throwing an exception.

One possibility: you're incorrectly "sharing" Session or Entities, via member field(s) of your servlet or controller. This is the main reason 'synchronized' would change your error symptoms.. Short solution: don't ever do this. Sessions and Entities shouldn't & don't work this way -- each Request should get processed independently.

Another possibility: unsaved-value defaults to 0 for "int" PK fields. You may be able to type these as "Integer" instead, if you really want to use 0 as a valid PK value.

Third suggestion: use Hibernate Session explicitly, learn to write simple correct code that works, then load the Java source for Hibernate/ Spring libraries so you can read & understand what these libraries are actually doing for you.