-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Problems with optimistic / pessimistic lock ...
PostPosted: Tue Nov 27, 2007 5:22 pm 
Newbie

Joined: Thu Apr 26, 2007 2:42 pm
Posts: 6
Hi everybody,

I have the following situation, and I would like to check if there is any 'best-practice' or workaround for it.

I have an Entity, which has @Version property setted, in 95% of the cases, the optimistic locking is fine.

For one process, which has high concurrency (is only executed 1 hour at night), I need to make a pessimistic lock on this entity.

What I do is:

MyEntity o = em.find(MyEntity.class, myKey);
em.lock(o, LockModeType.READ);
....

The problem that we have is that the lock sentence throw an OptimisticLockException.
I think that between we read the entity and we lock them, other threads are modifying it.

Is it right to get that exception ?
Is it possible to read the entity using JPA locking it in the first read ?
Is it possible to have an entity which use optimistic lock in some situations and pessimistic lock in others ?

Thanks in advance

Best Regards

Atuin


Hibernate version: 3.2.0.cr2

Full stack trace of any exception that occurs:

Hibernate:
select
SEA_ID
from
CRP_ACT_SESSION_EN_CURSO
where
SEA_ID =?
and SGUTIMESTAMP =? for update

[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,322. DEBUG AbstractBatcher:476 - preparing statement
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,322. DEBUG LongType:80 - binding '302' to parameter: 1
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,322. DEBUG LongType:80 - binding '5' to parameter: 2
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,338. DEBUG AbstractBatcher:366 - about to close PreparedStatement (
open PreparedStatements: 1, globally: 1)
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,338. DEBUG AbstractBatcher:525 - closing statement
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,338. DEBUG ConnectionManager:398 - aggressively releasing JDBC conn
ection
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,338. DEBUG ConnectionManager:435 - releasing JDBC connection [ (ope
n PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
[ACTIVE] ExecuteThread: '6' for queue: 'weblogic.kernel.Default (self-tuning)' -
--> 16:33:35,338. ERROR CrpActualizadorAppl:91 - Exception de updateSession = or
g.hibernate.StaleObjectStateException: Row was updated or deleted by another tra
nsaction (or unsaved-value mapping was incorrect): [crm.appl.crp.actualizador.do
main.CrpSessionActualizadorDO#302]
javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateExcepti
on: Row was updated or deleted by another transaction (or unsaved-value mapping
was incorrect): [crm.appl.crp.actualizador.domain.CrpSessionActualizadorDO#302]
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException
(AbstractEntityManagerImpl.java:551)
at org.hibernate.ejb.AbstractEntityManagerImpl.lock(AbstractEntityManage
rImpl.java:340)
at crm.core.persistence.FwkAuditorEntityManager.lock(FwkAuditorEntityMan
ager.java:172)
at crm.appl.crp.actualizador.appl.CrpActualizadorAppl.updateSession(CrpA
ctualizadorAppl.java:120)
at crm.appl.crp.actualizador.appl.CrpActualizadorEjbSn.updateSession(Crp
ActualizadorEjbSn.java:82)
at crm.appl.crp.actualizador.appl.CrpActualizadorEjbSn_au1gi7_EOImpl.upd
ateSession(CrpActualizadorEjbSn_au1gi7_EOImpl.java:279)
at crm.appl.crp.actualizador.appl.CrpActualizadorRmBDlg.updateSession(Cr
pActualizadorRmBDlg.java:99)
at crm.appl.crp.actualizador.appl.CrpActualizadorAppl.process(CrpActuali
zadorAppl.java:177)
at crm.appl.crp.actualizador.appl.CrpActualizadorEjbSn.process(CrpActual
izadorEjbSn.java:152)
at crm.appl.crp.actualizador.appl.CrpActualizadorEjbSn_au1gi7_EOImpl.pro
cess(CrpActualizadorEjbSn_au1gi7_EOImpl.java:207)
at crm.appl.crp.actualizador.appl.CrpActualizadorEjbSn_au1gi7_EOImpl_WLS
kel.invoke(Unknown Source)
at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:517)
at weblogic.rmi.cluster.ClusterableServerRef.invoke(ClusterableServerRef
.java:224)
at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:407)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(Authenticate
dSubject.java:363)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:
147)
at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.jav
a:403)
at weblogic.rmi.internal.BasicServerRef.access$300(BasicServerRef.java:5
6)
at weblogic.rmi.internal.BasicServerRef$BasicExecuteRequest.run(BasicSer
verRef.java:934)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:181)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted b
y another transaction (or unsaved-value mapping was incorrect): [crm.appl.crp.ac
tualizador.domain.CrpSessionActualizadorDO#302]
at org.hibernate.dialect.lock.SelectLockingStrategy.lock(SelectLockingSt
rategy.java:78)
at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractE
ntityPersister.java:1282)
at org.hibernate.event.def.AbstractLockUpgradeEventListener.upgradeLock(
AbstractLockUpgradeEventListener.java:88)
at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEv
entListener.java:64)
at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:586)
at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:578)
at org.hibernate.ejb.AbstractEntityManagerImpl.lock(AbstractEntityManage
rImpl.java:337)
... 19 more


Name and version of the database you are using: Oracle 10g

Debug level Hibernate log excerpt: DEBUG


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 06, 2008 1:20 pm 
Newbie

Joined: Thu Apr 26, 2007 2:42 pm
Posts: 6
a mi tambien me paso!!!!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 08, 2008 1:03 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
interesting problem, maybe a native SQL query and by setting the right lock mode

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 14, 2008 10:03 pm 
Newbie

Joined: Fri Mar 14, 2008 9:37 pm
Posts: 1
I would like to know the solution, too.
I have a similar issue on jBPM which use Hibernate as a persistent engine. DB is oracle 10g.

When I call session.lock(obj, LockMode.UPGRADE), hibernate seems like incrementing version (why for locking???), and same operation to the same object in another thread throw StaleObjectStateException.
This is basic feature we need for concurrent operation, and very easy to implement with SQL based programming with "select for update".

So, I tried to called "select for update" instead of using session.lock(), and this oeration worked as I expected, but when committing transaction, later thread throw StaleObjectStateException.

OK, then I load object after getting lock (after select for update) by session.load(id, class, LockMode.UPGRADE), but surprisingly the object returned still had old version, even DB record was committed and version was incremented.

I am doing something wrong???


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 21, 2008 12:50 pm 
Newbie

Joined: Fri Mar 21, 2008 12:31 pm
Posts: 1
The issue is that Hibernate has no awareness that the object is locked. It will create the correct SQL - (SELECT... FOR UPDATE...), but there's no way for Hibernate to know that the row in the database is locked. From Hibernate's perspective the execution of the (waiting) JDBC statement is just slow. Once the lock is released, Hibernate will still compare the version returned by the query to the version that exists in the first-level cache (Session.persistenceContext). If the versions differ, Hibernate throws a StaleObjectStateException.

An odd thing is that Query provides the ability to control the behavior in terms of the SECOND-level cache by using setCacheMode(). However, there seems to be no corresponding capability in terms of the first-level cache. For instance Query.setCacheMode(CacheMode.REFRESH) will cause the query to ignore the object in the second-level cache and update it with the value from the database.

My workaround was to evict the object from the session prior to fetching in the situations in which high concurrency was expected. This avoids the version comparison since there will be no existing version in the first-level cache when the waiting JDBC statement is able to continue. It would be nice to have the same behavior as Query.setCacheMode() that applies to the first-level cache.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.