StaleObjectStateException with Hibernate in read operation?

I am using Hibernate in a Spring DefaultMessageLisenerContainer listener.

When I allow a listener to work with multiple threads, I often come across this StaleStateException for a read-only operation:

 Query q = session.createQuery("SELECT k FROM Keyword k WHERE k.name = :name").setParameter("name", keywordName); List<Keyword> kws = q.list() 

An exception is thrown in q.list ():

optimistic blocking failed; org.hibernate.StaleObjectStateException nested exception: the row was updated or another transaction was deleted (or incorrect matching of inappropriate values)

 Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.aurora.common.model.Keyword#7550] at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1934) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2578) at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2478) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2805) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:114) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:267) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:259) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:179) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64) at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1175) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1251) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) 

This is really strange, because the read operation should read a new copy from the database, and not check for a version conflict and throw a StaleObjectStateException .

The name attribute is not the primary key of the Keyword object.

UPDATE : My data access code: I use Spring HibernateTransactionManager that support the Hibernate session associated with the stream. The Hibernate session is retrieved using the SessionFactory.getCurrentSession () method.

Each transaction wraps the caller's call by assigning a HibernateTransactionManager MessageListenerContainer:

 <jms:listener-container connection-factory="connectionFactory" concurrency="3-3" prefetch="6" transaction-manager="transactionManager"> <jms:listener destination="${requests}" response-destination="${replies}" ref="chunkHandler" method="handleChunk" /> </jms:listener-container> 

UPDATE: As in the proposed answer, there may be other operations causing a staleObjectStateException. I tried to output Session.isDirty () for all other operations before this. All read operations. Interestingly, the session is indeed marked as dirty after selecting a keyword by name. The actual code looks something like this:

 for (String n : keywordNames) { Keyword k = keywordDao.getKeywordByName(n); } 

The session is dirty after the first iteration. (Binding KeywordDao.getKeywordByName as above). Any ideas? Thanks, Khue.

+6
source share
3 answers

I believe the other answers are incorrect. Access to the line does not exist, does not give a StaleObjectStateException and simply asks that the object will not trigger an optimistic lock for this object.

Further checking the stack trace will give some clues:

at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) When you call query.list ()

at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1175) Hibernate will determine if automatic session cleanup is required. For some reason, Hibernate believes it needs an automatic flash. (Perhaps due to the fact that you previously did an update for some Keyword objects in the same session or other objects ... this is something I can not say honestly)

at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2805) Then Hibernate will clear all changes in the session to DB. And here the StaleObjectStateException problem arises, which means Optimistic Concurrency validation failure. An optimistic Concurrency check failure MAY or MAY NOT be bound to a Keyword object (since it just clears all updated entities in the session prior to DB). However, in your case, this is actually related to Keyword entity ( Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ncs.singtel.aurora.common.model.Keyword#7550] )

Please check the reason for the failed Concurrency attempt. Usually we simply rebuild the optimistic Concurrency exception for the caller and let the caller decide whether they want to call this function again. However, it all depends on your design.

+6
source

stalestateException occurs when we try to access a string that does not exist. check keyword.getName() to see what it returns.

0
source

Some other transactions may update the Keyword object at the same time as reading, and your read operation may lead to the creation of Stale objects.

This is an optimistic block. You may consider pessimistic blocking, but this will seriously affect performance.

I would suggest catch StaleObjectStateException and try to read again.

0
source

All Articles