1

Spring 3.0.4-RELEASE、JPA 2.0 を Hibernate をプロバイダーとして使用し、JTA JOTM をアプリケーションのトランザクションに使用しています。entityManager.mergeエンティティ オブジェクトを呼び出すと、次のエラーが発生しました。

org.objectweb.jotm.SubCoordinator commit_one_phase
INFO: Rollback during beforeCompletion in SubCoordinator.commit_one_phase
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException 
      at
 org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1012)    

このエラーは、Talend ETL ジョブを介してデータベース (MySQL) にデータを直接挿入した結果として発生しました。@Versionデータベース内の列に値があることに気付き、NULL値を 0 に設定することにしました。これで問題が解決しました。

@Version列ができないのはなぜNULLですか? 他の誰かがこの問題に遭遇しましたか? ありがとう。

4

2 に答える 2

1

エンティティ オブジェクトで entityManager.merge を呼び出すと、次のエラーが発生しました。

ここで何が起こっているのかを完全に理解したい場合は、ログを有効にして、何が結果として発生しているのかを正確に確認してくださいRollbackException(「悪い」SQL と思われます)。

を取得していないことに注意してくださいOptimisticLockException。Hibernate がバージョンによって何らかの形で混乱していると思いますNULL。私は実際に問題を掘り下げたわけではなく、詳細に説明することはできませんが、Hibernate はUPDATEマージに期待されるステートメントを生成していないようです。

@Version 列を NULL にできないのはなぜですか? 他の誰かがこの問題に遭遇しましたか? ありがとう。

私が書いたように、正確な理由を示すことはできませんが、答えたくなる誘惑にかられます: それは Hibernate が期待する値ではないからです。Hibernate は0バージョン列の初期値として開始します。私の提案は、Hibernate の期待を尊重し、それをデフォルト値として設定することです。

初期値として設定すると問題が発生する理由を理解したい場合NULLは、Hibernate のコードをデバッグする必要があります。しかし、正直なところ、これは時間の無駄のように思えます。Hibernate を使用しているので、Hibernate の API をバイパスするときは Hibernate の動作を尊重/模倣するだけです。

于 2010-11-06T22:43:24.490 に答える
0

どのような動作を期待していますか?

デタッチされたオブジェクトに対して実行するmergeと、デタッチされたエンティティのバージョンがデータベースのバージョンと一致しない場合、楽観的同時実行例外がスローされます。あなたの場合、この例外はにラップされていると思いますUnexpectedRollbackException。切り離されたエンティティのバージョンが の場合0、データベースのバージョン列を設定すると、0これが解決されます。

本当の解決策は、外部ソフトウェアがエンティティを変更したときに、データベース内のエンティティのバージョンをインクリメントすることです。これは、楽観的ロック戦略と一致します。

于 2010-11-05T23:20:42.717 に答える