5

コンテナー管理トランザクション(JBoss AS 6.1.0.Final)のプロバイダーとしてHibernateでJPAを使用しています。

アプリに特定の例外階層があり、あらゆる状況で何をすべきかを定義できるため、きめ細かい例外処理を実装しようとしています。それで、私は何時間も調査してきましたが、例外処理は常に「明確にするために」省略されているか、例外eを処理する単純なtry-catchブロックであるため、ドキュメントはあいまいで、例はやや生々しいものです。

たとえば、次のコードを考えてみましょう。

public void deleteCompany(ICompany company) throws MyException1, MyException2 {
    if(entityManager != null){
        if(company !=null) {
            try {
                ICompany companyReference= entityManager.getReference(Company.class, company.getId());
                entityManager.remove(managedCompany);
                entityManager.flush();
            } catch(EntityNotFoundException companyDoesNotExist) {
                //Wrap & Throw
            }
        } else {
        throw new MyException1("An error occurred while attempting to save a null instance of a company");
        }
    } else {
        throw new MyException2("The entity manager instance is null");
    }   
}

ここでスタックしているため、catchブロックは空白です...ユーザーが存在しないレコードを削除しようとしていることをシステムに警告するために、どの例外をキャッチする必要があるかわかりません。

私の具体的な質問は、そのキャッチブロックでHibernateの例外をキャッチできますか、それともJPAの例外をキャッチする必要がありますか?JPAがプロバイダーの例外をラップしていると主張する情報源をいくつか見つけましたが、それは私には奇妙に聞こえます。また、flush()メソッドを呼び出すと、データベースアクセスと操作の例外をキャッチできることがわかりました。これは、トランザクションがコンテナーによって管理され、deleteCompanyを呼び出した後にコミットメントがさらにステップアップするためです。

ありがとうございました。

編集: @ApplicationException(rollback = true)で注釈が付けられた独自の例外でキャッチした例外をラップしているので、それらを再度スローして、より明確に処理できます。

編集2:コードを更新しました。削除前のマージは、データベースにない場合でも会社を存続させ、削除が毎回成功する原因になります。現在、例外がスローされており、Perceptionによって提案されているように、JPA例外をキャッチするさまざまな状況でどのように動作するかをテストしています。

編集3:今は機能しています!、そのマージ呼び出しのためにエラーが部分的に私のコードにあったことがわかりました。最初に参照を取得し、後で削除を試みると、トリックが実行されます。これにより、EntityNotFoundExceptionをキャッチし、ラップして、再度スローすることができました。

4

1 に答える 1

5

ベンダーの例外はJPA例外に組み込まれるため、確実にキャッチされることはありません。問題のポイントでいくつかの例外タイプのいずれかが発生している可能性があることに注意してください。

  • IllegalArgumentException-デタッチされたオブジェクトまたはエンティティ以外のオブジェクトの場合
  • IllegalStateException-エンティティマネージャーは閉鎖されています
  • PersistenceException-少なくとも、そのサブクラス。これは、関連付けられたトランザクションがなく、呼び出しにトランザクションが必要な場合、データベース制約が操作を拒否した場合、トランザクションに時間がかかりすぎる場合など、さまざまな理由で取得できます。

ある種のカスタムアプリケーション例外でそれらを再ラップすることを計画していない限り、これらの例外をこのような低レベルでキャッチするべきではありません。そのルートを使用する場合は、スタックトレースが失われないように、必ず元の例外をラップしてください。

JPA Entity Managerによって生成されるすべての例外は、実行時の例外であることに注意してください。

于 2012-04-17T21:53:29.723 に答える