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 セッションに保存されていますか? それとも、データベースからエンティティをフェッチして、リクエストが到着したときに変更を加えていますか?

アプリケーションサーバーでリクエストはどのように処理されますか? 各リクエストが独自のスレッドによって処理される場合はありますか?

それらはスレッドプールによって処理されます。したがって、各リクエストは「独自の」スレッドを取得しませんが、アクティブな各リクエストはいつでもセオアレートスレッドによって処理されています。(または、1 つが解放されるのを待っている列に並んでいます。)

エラーを見ると、それらが (http--10.10.4.16-8080-1) および (http--10.10.4.16-8080-7) と呼ばれていることに気付きました。末尾の数字はリクエストを処理したスレッド番号ですか?

全体がスレッドの名前です。Tomcat は数字を一意にするために最後に数字を付けますが、その # には、Tomcat によって割り当てられた任意の連続した文字列以外の特別な意味はありません。

optimistiLockException は、JPA/Hibernate がコミットを発行する前に同じメッセージを更新しようとしたことを示しています。関連するコードを同期ブロックに配置した場合、同期ブロックが使用可能になったときにリクエストが処理された順序になるようにするにはどうすればよいですか?

順序が重要な場合は、処理する前に何らかのキューに入れる必要があります。同期は、待機中のスレッドが実行される順序について保証しません。このプロセスが失敗してはならない場合は、アプリケーション サーバーで同期するのではなく、データベースでペシミスティック ロックを使用することを検討してください。テーブルを使用する他のスレッドは、同期を気にせず、とにかく例外を引き起こす可能性があります。

コミットされていない変更がある場合、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 に答える