Я только что изучил оптимистичную блокировку Hibernate на прошлой неделе и представил ее моему приложению, написанному с помощью Spring JPA и MySQL DB.сбой оптимистической блокировки; Вложенное исключение - org.hibernate.StaleObjectStateException при сохранении записи с CrendRepository Spring Data
My Entity выглядит это, Version
аннотацию только что был добавлен,
@Entity
public class Instance {
...
@javax.persistence.Version
private Date updateTime;
...
pubic Instance() {
this.updateTime = new Date();
}
}
И у меня есть org.springframework.data.repository.CrudRepository
, используемый для сохраняющихся данных. В то время как я проверил обновление существующей записи работает нормально, проблема в том, что будет бросать исключение, когда сохраняющиеся новый объект,
inst = new Inst();
instanceRepo.save(inst);
Исключение брошено является
org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [Instance] with identifier [a5deddb9-d76c-433f-8b0d-e50cbf8f601e]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) :
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy139.save(Unknown Source)
Это просто первый вызов настойчивости и я не думаю, что существует несколько потоков, пытающихся обновить эту запись, поэтому я смущен, почему это исключение выбрано.
Также я попытался проследить в исходный код, а вот некоторые результаты могут быть полезны,
При вызове, лежащих в основе
org.springframework.data.jpa.repository.support.SimpleJpaRepository#save(S)
, как вставил ниже, код будет идти на слияния логики, хотя это новый рекорд,public <S extends T> S save(S entity) { if (entityInformation.isNew(entity)) { em.persist(entity); return entity; } else { return em.merge(entity); } }
исключение происходит, когда он пытается совершить сделку и промывать DB.
это не то, что должно произойти в случае, если у вас есть несвежий объект .. поэтому мы используем оптимистическую блокировку? – Zulfi