Hi, guys.
I'm using hibernate 3.6.0 as persistence provider for JPA inside JBoss AS 6. My scenario is:
1. Create Entity.
2. Persist Entity using EntityManager.persist(myEntity).
3. Call EntityManager.lock(myEntity).
All the steps above are done inside the same transaction. As a result I get:
Code:
Caused by: javax.persistence.OptimisticLockException
at org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:1240) [:3.6.0.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1166) [:3.6.0.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.lock(AbstractEntityManagerImpl.java:918) [:3.6.0.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.lock(AbstractEntityManagerImpl.java:902) [:3.6.0.Final]
at org.jboss.jpa.impl.tx.TransactionScopedEntityManager.lock(TransactionScopedEntityManager.java:132) [:2.0.0]
at com.MyBean.doIt(AssistantServiceBean.java:78) [:]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_22]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_22]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_22]
at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_22]
at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:122) [jboss-aop.jar:2.2.1.GA]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.interceptors.container.ContainerMethodInvocationWrapper.invokeNext(ContainerMethodInvocationWrapper.java:72) [:1.1.3]
at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.invoke(InterceptorSequencer.java:76) [:1.1.3]
at org.jboss.ejb3.interceptors.aop.InterceptorSequencer.aroundInvoke(InterceptorSequencer.java:62) [:1.1.3]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_22]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [:1.6.0_22]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [:1.6.0_22]
at java.lang.reflect.Method.invoke(Method.java:597) [:1.6.0_22]
at org.jboss.aop.advice.PerJoinpointAdvice.invoke(PerJoinpointAdvice.java:174) [jboss-aop.jar:2.2.1.GA]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.fillMethod(InvocationContextInterceptor.java:74) [:1.1.3]
at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_fillMethod_896176329.invoke(InvocationContextInterceptor_z_fillMethod_896176329.java) [:]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor.setup(InvocationContextInterceptor.java:90) [:1.1.3]
at org.jboss.aop.advice.org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor_z_setup_896176329.invoke(InvocationContextInterceptor_z_setup_896176329.java) [:]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.async.impl.interceptor.AsynchronousServerInterceptor.invoke(AsynchronousServerInterceptor.java:128) [:1.7.17]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:62) [:1.7.17]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:56) [:1.7.17]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:90) [jboss-aop.jar:2.2.1.GA]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47) [:1.7.17]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.tx.NullInterceptor.invoke(NullInterceptor.java:42) [:1.0.3]
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102) [jboss-aop.jar:2.2.1.GA]
at org.jboss.ejb3.core.context.SessionInvocationContextAdapter.proceed(SessionInvocationContextAdapter.java:95) [:1.7.17]
at org.jboss.ejb3.tx2.impl.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:223) [:0.0.1]
... 68 more
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.MyClass#ad2d5c4d-3add-491b-a049-9234611e6c7b]
at org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy.lock(PessimisticWriteSelectLockingStrategy.java:101) [:3.6.0.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractEntityPersister.java:1425) [:3.6.0.Final]
at org.hibernate.event.def.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:110) [:3.6.0.Final]
at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:86) [:3.6.0.Final]
at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:774) [:3.6.0.Final]
at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:766) [:3.6.0.Final]
at org.hibernate.impl.SessionImpl.access$600(SessionImpl.java:156) [:3.6.0.Final]
at org.hibernate.impl.SessionImpl$LockRequestImpl.lock(SessionImpl.java:2369) [:3.6.0.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.lock(AbstractEntityManagerImpl.java:914) [:3.6.0.Final]
... 109 more
I far as I understand from documentation it's expected behavior, i.e. Hibernate doesn't flush objects during lock method call. To workaround this I can call flush explicitly on EntityManager before calling lock. But I don't like this due to performance reasons. So my question is : are there any other options to lock object which is absent in database at the moment of lock call? May be some API to know that object I'm trying to lock is just created and absent in database, in order to call flush only in such cases?