2012-05-31 106 views
1

我有一个运行在应用程序服务器上的spring MVC应用程序。对应用程序的每个请求都会导致Hibernate调用entityManager.merge()更新数据库中的一行。应用服务器线程和JPA/Hibernate乐观锁定 - OptimisticLockException

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

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没有尝试更新消息,如果有未提交的更改?

感谢

回答

2

的补丁提供给您取决于您​​如何architectured你的层次,并在那里你正在合并的实体从何而来。分离的实体是通过弹簧数据联编程序组装的,还是存储在Web会话中,还是从数据库中获取实体并在请求到达时对其进行更改?

How are the requests handled on the application server? Is the case that each request is processed by its own thread?

它们由线程池处理。因此,每个请求都不会得到“自己的”线程,但是在任何给定时间,每个活动请求正在由seoarate线程处理,是的。 (或在等待一个空闲的队列中)。

Looking at the error i noticed that they were referred to as (http--10.10.4.16-8080-1) and (http--10.10.4.16-8080-7). Is the number at the end the thread number that processed the request?

整个事情就是线程的名字。 Tomcat将数字放在最后以使它们唯一,但除了由tomcat指定的任意连续字符串外,#没有任何特殊含义。

The optimistiLockException suggests that there was an attempt to update the same message before JPA/Hibernate issued a commit. If i put the relevant code in a synchronized block, how do i ensure that the order the requests came in is the order they are processed when the synchronized block is available?

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

Is there a way to instruct JPA/Hibernate to not attempt to update the message if there are uncommitted changes?

不是真的,没有检查,如果实体已经挂起在内存中缓存在其他一些会议上的更新任何直接的方式。 OptimisticLock检查知道其他人是否进行了更改的机制。

+0

+1:请注意,即使您对合并进行排队,除第一个外,所有除第一个外都将失败并出现OptimisticLockException,因为它们都将tr y将分离的对象与过时的版本字段合并。 –

+0

是的,必须排队整个工作,而不仅仅是合并。 – Affe

+0

感谢情与JB。我会尝试实现一个排队机制来解决它。 – ziggy

0

javax.persistence。OptimisticLockException

当你的实体得到更新具有自动生成的ID ..Try添加注释

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 

如果不列入工作尝试

@OptimisticLock(excluded=true) 

参考,通常会出现此异常:Link