2009-07-23 4 views
1

私はSpringとHibernateを使用しています。取引のためのAtomikos。私は注釈ベースのトランザクションを使用します。私はDAOオブジェクトを持っていて、メソッドの1つでは、オブジェクトを保存するためにentityManager.persist()を呼び出します。 更新中にORAエラーが発生すると、たとえば、制約違反、または列の1つがデータベース内で定義されたワット数を超えるなど、SpringによってスローされるGenericJDBCExceptionではなくJTAUnexpectedRollbackExceptionが発生します。 私はそれをキャッチするために試してみることを試みたが、私はそこに例外を取得していない。 Hibernateは、トランザクションのコミット中に発生するフラッシュ中の実際の更新ステートメントを実行していると思われます。したがって、UnexpectedRollbackExceptionが発生します。HibernateのフラッシュとJTAUnexpectedRollbackException

これを回避し、UnexpectedRollbackExceptionの代わりにGenericJDBCExceptionを取得するにはどうすればよいですか?

+0

JTAUnexpectedRollbackExceptionの代わりにGenericJDBCExceptionを取得することが重要なのはなぜですか?なぜトランザクションがコミットするのではなく、永続性に関する例外をキャッチしたいのですか? –

+0

私のライブラリを呼び出すクライアントがUnexpectedRollbackを取得すると、何が間違っているかの手がかりがないので、GenericJDBCExceptionはSQLExceptionのスタックトレースを表示しますが、ロールバック例外には完全なスタックトレースがありません。 – Arvind

+0

トランザクションを管理するためにSpringを使用する利点の一部は、下位のレイヤーにかかわらず一様な例外を持っています。 –

答えて

1

まず、免責事項:私はAtomikosを使用しません。私はそれが問題のエラーと関係があるとは思わないが、確かにそれを知ることはできない。

私は、Spring/Hibernateアプリケーションでこれまでに非常に似た問題を抱えていました。 Hibernateは、実際にフラッシュ中にデータベースへのセッション更新を伝播するだけです。問題は、フラッシュモードに応じて異なる時間にフラッシュが行われることです。デフォルトではAUTOになります。これは、セッションにクエリ結果に影響する可能性のある更新が含まれている場合、クエリの実行前にフラッシュが発生する可能性があることを意味します。

entityManager.persist()を呼び出した直後に手動でentityManager.flush()を呼び出し、その時点で例外をキャッチすることができます。この場合の欠点は、フラッシュによってバッチ更新が中断されるため、単一のトランザクション内で同じエンティティタイプに対して複数の挿入/更新を行うと、パフォーマンスが大幅に低下する可能性があることです。

B)フラッシュモードをCOMMITに設定すると、トランザクションがコミットされるまで(または手動でflush()が呼び出されるまで)フラッシュを遅らせることができます。その時点で例外をキャッチすることができます。または、Atomikosによって不可能であることが判明した場合は、コミットの直前に手動でflush()を呼び出すことができます(サービスコールの終了時など)。欠点は、これがオプションAより難しいということです(私の場合は難しく、Atomikosではもっと難しいかもしれません - 私は分かりません)。

1

それが原因か、下流の原因のカップルだとUnexpectedRollbackExceptionGenericJDBCExceptionが含まれている場合は、プログラムでgetCause()getRootCause()メソッドを使用して、それを取得することができますし、それを再スローします。

try { 
    em.flush(); 
} catch (UnexpectedRollbackException e) { 
    if (e.getRootCause() instanceof GenericJDBCException) { 
     throw e.getRootCause(); 
    } 
} 

私はgetRootCause()またはgetCause()[.getCause()]リターンGenericJDBCException場合、デバッガで、おそらく、それを見つける必要があることを確認していません。