java - 在 Spring 获取 org.springframework.orm.ObjectOptimisticLockingFailureException

标签 java spring hibernate spring-boot jpa

我创建了一个函数,它试图在启用版本的数据库中保存一些东西,因此它可以给出乐观锁异常。我捕获异常并在从数据库中获取后重试。我也每次都使用@transactional 注释来启动一个新事务。但是我什至在调用我的保存函数之前就得到了 org.springframework.orm.ObjectOptimisticLockingFailureException。

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handleExecution(@NonNull final Execution execution, final Map<String, Object> data, final String pattern) {

    log.info("Processing notification pattern {} with data {} for execution {}",pattern,data,execution);

    if (ExecutionStatus.PROCESSING.equals(execution.getStatus()) || ExecutionStatus.WAITING.equals(execution.getStatus())) {
        //Put the received notification in the execution queue

        List<Map<String, Object>> notificationQueue = execution.getNotificationQueue();
        Map<String,Object> notificationMap = new HashMap<>();
        notificationMap.put(pattern, data);
        notificationQueue.add(notificationMap);
        execution.setNotificationQueue(notificationQueue);

        try
        {
            executionBuilder.save(execution);
        }
        catch(OptimisticLockingFailureException e)
        {
            log.error("Save of execution {} failed due to optimistic locking, retrying",execution);
            //Fetch the object again and call again
            Optional<Execution> savedExecution = executionBuilder.findOne(execution.getId());
            if(savedExecution.isPresent())
            {
                handleExecution(savedExecution.get(),data, pattern);
            }
        }

    }
}

我得到的详细异常是:

2018-07-11 08:09:39.408  INFO 8251 --- [thread_pool_executor-45] 
o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of 

batch it still contained JDBC statements
2018-07-11 08:09:39.408 ERROR 8251 --- [thread_pool_executor-45] reactor.bus.EventBus                     : Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

org.springframework.orm.ObjectOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:320) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) ~[spring-orm-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) ~[spring-aop-4.3.7.RELEASE.jar:4.3.7.RELEASE]
        at com.gor.platform.process.support.service.builder.ExecutionBuilderImpl$$EnhancerBySpringCGLIB$$a036b2e6.patch(<generated>) ~[process-service-2.0-SNAPSHOT.jar:2.0-SNAPSHOT]
        at com.gor.platform.process.support.service.event.receiver.ProcessEventReceiver.accept(ProcessEventReceiver.java:58) ~[process-service-2.0-SNAPSHOT.jar:2.0-SNAPSHOT]
        at com.gor.platform.process.support.service.event.receiver.ProcessEventReceiver.accept(ProcessEventReceiver.java:23) ~[process-service-2.0-SNAPSHOT.jar:2.0-SNAPSHOT]
        at reactor.bus.EventBus$3.accept(EventBus.java:317) ~[reactor-bus-2.0.8.RELEASE.jar:na]
        at reactor.bus.EventBus$3.accept(EventBus.java:310) ~[reactor-bus-2.0.8.RELEASE.jar:na]
        at reactor.bus.routing.ConsumerFilteringRouter.route(ConsumerFilteringRouter.java:72) ~[reactor-bus-2.0.8.RELEASE.jar:na]
        at reactor.bus.EventBus.accept(EventBus.java:591) [reactor-bus-2.0.8.RELEASE.jar:na]
        at reactor.bus.EventBus.accept(EventBus.java:63) [reactor-bus-2.0.8.RELEASE.jar:na]
        at reactor.core.dispatch.AbstractLifecycleDispatcher.route(AbstractLifecycleDispatcher.java:160) [reactor-core-2.0.8.RELEASE.jar:na]
        at reactor.core.dispatch.MultiThreadDispatcher$MultiThreadTask.run(MultiThreadDispatcher.java:74) [reactor-core-2.0.8.RELEASE.jar:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
        at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:67) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:54) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3082) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2961) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3341) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
        at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]

executionBuilder.save 内部调用 dao.save,这在堆栈跟踪中是看不到的。为什么在调用保存之前就会抛出此异常。当调用保存时,异常被捕获并且一切正常。但偶尔会在没有保存的情况下抛出此异常,因此不会被捕获。

我的直觉说它与@Transactional 有关。

关于我的应用程序是多线程的信息,许多线程可能同时修改相同的数据。

如有任何帮助,我们将不胜感激。

最佳答案

您可以使用 Controller 内的 Spring 重试选项处理乐观锁。 下载本类(class)

import org.springframework.retry.annotation.Retryable;

例如

@RequestMapping(value = CommonConstants.DETAILS_ADD_OR_UPDATE, method = RequestMethod.POST)
@Retryable(value = { StaleObjectStateException.class,
        HibernateOptimisticLockingFailureException.class }, maxAttempts = 1, backoff = @Backoff(delay = 5000))
public ResponseJson addOrUpdate(@RequestBody User user, HttpServletRequest request) {
    try{
    responseJson.setResponse(adminService.update(userId, user));
    }
    catch (DataIntegrityViolationException | ConstraintViolationException e) {
        ErrorInfo errorInfo = errorCodeHelper.getErrorInfo(CommonConstants.E1071_ERROR_CODE,
                CommonConstants.E1071_ERROR_DESCRIPTION);
        throw new ServiceException(errorInfo);
    }
    return responseJson;
}

这是最重要的添加方法

@Retryable(value = { StaleObjectStateException.class,
        HibernateOptimisticLockingFailureException.class }, maxAttempts = 1, backoff = @Backoff(delay = 5000))

关于java - 在 Spring 获取 org.springframework.orm.ObjectOptimisticLockingFailureException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51290047/

相关文章:

java - 如何使用 Spring Data 在代码中使用自动生成的 ID?

java - 使用 hibernate 将 null 保存为 id

java - 如果同时有很多请求,多线程是否会提高性能?

java - 如何通过Spring框架中的 Controller 使用查询字符串将参数发送到jsp页面?

Spring Reactor Webflux 调度器并行性

spring - 如何在Spring Boot中设置enableLoggingRequestDetails ='true'

java - Hibernate序列化/反序列化对象并保存

java - Ant Java 任务 : how to get output to console and a file-always record build output without shell redirection

java - Java中调用native代码如何判断是不是内存泄漏?

java - 由于 : java. io.SyncFailedException 导致 Cassandra 关闭:同步失败