如何解决为什么选择查询会在 JPA 休眠中触发乐观锁定错误?
抛出了一个 ObjectOptimisticLockingFailureException。我检查了日志,发现这个异常是由一个选择查询触发的。这很奇怪。
这是异常堆栈跟踪。
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:317)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerfactorybean.translateExceptionIfPossible(AbstractEntityManagerfactorybean.java:491)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy117.countOtherRoles(UnkNown Source)
at net.homecredit.mcd.app.service.UserRolePosService.countOtherRoles(UserRolePosService.java:315)
at net.homecredit.mcd.app.service.UserRolePosService.canRemoveEmployer(UserRolePosService.java:375)
at net.homecredit.mcd.app.service.UserRolePosService.deactivate(UserRolePosService.java:339)
at net.homecredit.mcd.app.service.UserRolePosService.fillRoleData(UserRolePosService.java:241)
at net.homecredit.mcd.app.service.UserRolePosService.fillRoleData(UserRolePosService.java:199)
at net.homecredit.mcd.app.service.UserRolePosService.fillRoleData(UserRolePosService.java:180)
at net.homecredit.mcd.app.service.pos.PosBusinessService.saveUserRole(PosBusinessService.java:224)
at net.homecredit.mcd.app.service.pos.PosBusinessService.updatePos(PosBusinessService.java:121)
at net.homecredit.mcd.app.service.pos.PosBusinessService$$FastClassBySpringcglib$$ad825d06.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.invokeJoinpoint(cglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at net.homecredit.mcd.common.security.ForbiddingSecurityInterceptor.invoke(ForbiddingSecurityInterceptor.java:17)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at net.homecredit.mcd.common.aop.AuditInterceptor.invoke(AuditInterceptor.java:21)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.cglibAopProxy$DynamicAdvisedInterceptor.intercept(cglibAopProxy.java:656)
at net.homecredit.mcd.app.service.pos.PosBusinessService$$EnhancerBySpringcglib$$7cfba5de.updatePos(<generated>)
at net.homecredit.mcd.app.service.homesis.kafka.HsisKafkaConsumer.updatePos(HsisKafkaConsumer.java:122)
at net.homecredit.mcd.app.service.homesis.kafka.HsisKafkaConsumer.updatePos(HsisKafkaConsumer.java:97)
at net.homecredit.mcd.app.service.homesis.kafka.HsisKafkaConsumer.consumePos(HsisKafkaConsumer.java:73)
at sun.reflect.GeneratedMethodAccessor871.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(UnkNown Source)
at java.lang.reflect.Method.invoke(UnkNown Source)
at org.springframework.messaging.handler.invocation.invocableHandlerMethod.doInvoke(invocableHandlerMethod.java:180)
at org.springframework.messaging.handler.invocation.invocableHandlerMethod.invoke(invocableHandlerMethod.java:112)
at org.springframework.kafka.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:48)
at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:174)
at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:82)
at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:50)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:975)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:959)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:901)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:786)
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:656)
at java.util.concurrent.Executors$RunnableAdapter.call(UnkNown Source)
at java.util.concurrent.FutureTask.run(UnkNown Source)
at java.lang.Thread.run(UnkNown Source)
Caused by: org.hibernate.staleobjectstateexception: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [net.homecredit.mcd.app.domain.Pos#2307536273]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2400)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3202)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3077)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3457)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:589)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50)
at org.hibernate.internal.SessionImpl.autoFlushIfrequired(SessionImpl.java:1398)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1483)
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1445)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1463)
at net.homecredit.mcd.app.dao.UserRolePosDao.countOtherRoles(UserRolePosDao.java:225)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(UnkNown Source)
at java.lang.reflect.Method.invoke(UnkNown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 47 common frames omitted
日志显示它在更新 POS 表时遇到了乐观锁错误。这条线
"at net.homecredit.mcd.app.dao.UserRolePosDao.countOtherRoles(UserRolePosDao.java:225)"
,触发此乐观错误。我检查了这段代码。
public Integer countOtherRoles(User user,UserRolePos userRole) {
return em.createNamedQuery(UserRolePos.COUNT_OTHER_ROLE_FOR_USER,Long.class)
.setParameter("user",user)
.setParameter("userRole",userRole)
.getSingleResult().intValue();
}
相关查询如下
@NamedQuery(name = UserRolePos.COUNT_OTHER_ROLE_FOR_USER,query = "SELECT COUNT(urp) FROM UserRolePos urp " +
"WHERE urp.user = :user " +
"AND urp != :userRole "
)
这只是对另一个 UserRole 表的选择查询,为什么会触发 POS 表的乐观锁错误?
解决方法
如果您仔细查看堆栈跟踪,您会注意到 Hibernate 会“自动刷新”。当您的持久性上下文中有“脏”实体并尝试使用与脏实体的表相交的表进行查询时,就会发生这种情况。如果它不刷新脏条目,您可能会得到错误的结果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。