Hi all,
I have asked this in the Seam forum but nobody seems to be interested. And this may as well be the correct place to post anyway.
This is a Seam based web-application using Hibernate as the JPA provider.
I have a database table that is updated in a highly concurrent manner. Further, the updates are done via different asynchronous event handlers.
I have put a version property in the entity class to get optimistic lock exceptions in order not to have any lost updates. I have read about this in a lot of places including the documentation but instead of retrying the update operation after getting an optimistic lock, I am trying to avoid those exceptions completely by properly synchronizing the Java code that updates the table.
So for example a single thread calls below method to update an entity instance:
Code:
public void updateMethod(Long id) {
synchronized(GLOBAL_LOCK) {
EntityManager entityManager = (EntityManager) Component.getInstance("entityManager");
SomeEntity entity = entityManager.find(SomeEntity.class, id);
entityManager.refresh(entity);
entityManager.lock(entity, LockModeType.WRITE);
// do some stuff to modify the entity
entityManager.flush();
}
}
Here even though I am synchronizing the method on a global level (lock is a singleton per JVM), I get javax.persistence.OptimisticLockException. - javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
I am simply wondering how this can happen even though the EntityManager objects and the underlying transactions are different in different threads. I checked this by debugging and verified it: they are different in different Asynchronous Seam events. Since the transactions and entityManager's are different instances and the code is mutually exclusive, I shouldn't be hitting any OptimisticLockException's right? Any ideas why this is happening? How come the entityManager gets an outdated version of the entity even though it is refreshed, flushed, synchronized, etc...? Where does it get the outdated entity from? Cache or something?
I have tested with entityManager.close() added after the flush() but that didn't help either.
Any feedback is appreciated.
Regards, Bora.