1

我在应用程序服务器上运行了一个 Spring MVC 应用程序。对应用程序的每个请求都会导致 Hibernate 调用 entityManager.merge() 来更新数据库中的一行。

我今天运行测试发送多个请求,并注意到我收到以下错误:

javax.persistence.OptimisticLockException
        at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:340) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:214) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:190) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:540) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) [resteasy-jaxrs-2.3.1.GA.jar:]
        at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50) [resteasy-jaxrs-2.3.1.GA.jar:]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.10.Final.jar:]
        at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.0.Final.jar:7.1.0.Final]
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:154) [jboss-as-web-7.1.0.Final.jar:7.1.0.Final]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.10.Final.jar:]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.10.Final.jar:]
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.10.Final.jar:]
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.10.Final.jar:]
        at java.lang.Thread.run(Thread.java:619) [rt.jar:1.6.0_20]

为了能够解决上述问题,我需要了解以下内容:

  • 应用服务器上的请求是如何处理的?是不是每个请求都由自己的线程处理?

  • 查看错误我注意到它们被称为(http--10.10.4.16-8080-1)和(http--10.10.4.16-8080-7)。最后的数字是处理请求的线程号吗?

  • optimistiLockException 表明在 JPA/Hibernate 发出提交之前尝试更新相同的消息。如果我将相关代码放在同步块中,我如何确保请求进入的顺序是同步块可用时处理它们的顺序?

  • 如果有未提交的更改,有没有办法指示 JPA/Hibernate 不要尝试更新消息?

谢谢

4

2 回答 2

2

您可用的修复取决于您如何构建您的层以及您要合并的实体来自何处。分离的实体是由 spring 数据绑定器组装的,还是存储在 Web 会话中,或者您是从数据库中获取实体并在请求到达时对其进行更改?

应用服务器上的请求是如何处理的?是不是每个请求都由自己的线程处理?

它们由线程池处理。因此,每个请求都不会获得“自己的”线程,但在任何给定时间,每个活动请求都由一个单独的线程处理,是的。(或者排队等待一个人释放。)

查看错误我注意到它们被称为(http--10.10.4.16-8080-1)和(http--10.10.4.16-8080-7)。最后的数字是处理请求的线程号吗?

整个事情就是线程的名称。Tomcat 将数字放在末尾以使它们唯一,但除了由 tomcat 分配的任意顺序字符串之外,# 没有任何特殊含义。

optimistiLockException 表明在 JPA/Hibernate 发出提交之前尝试更新相同的消息。如果我将相关代码放在同步块中,我如何确保请求进入的顺序是同步块可用时处理它们的顺序?

如果订单很重要,您需要在处理之前将它们放入某种队列中。同步不承诺等待线程执行的顺序。如果此过程不能失败,请考虑在数据库中使用悲观锁,而不是在应用服务器上同步。使用该表的其他一些线程可能不会打扰 sycnhing 并且无论如何都会导致异常。

如果有未提交的更改,有没有办法指示 JPA/Hibernate 不要尝试更新消息?

并非如此,没有任何直接的方法可以检查实体是否在其他会话的内存缓存中具有待处理的更新。OptimisticLock 检查了解其他人是否进行了更改的机制。

于 2012-05-31T16:06:25.973 回答
0

javax.persistence.OptimisticLockException

此异常通常发生在您的实体正在更新时,它具有自动生成的 id ..尝试添加注释

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

如果这不起作用,请尝试

@OptimisticLock(excluded=true)

参考:链接

于 2012-05-31T16:18:11.787 回答