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.