2

私は小さなJavaEEプロジェクトを構築しており、リポジトリクラスを持っています:

@Stateless
public class UserRepository extends AbstractRepository<User> {

    @PersistenceContext
    private EntityManager em;

    public User getByName(String username) {
       CriteriaBuilder criteriaBuilder = ...

       return em.createQuery(query).getSingleResult();
    }
}

そして、私はこの関数を使用する Service クラスを持っています:

@Stateless
public class UserService extends AbstractService<User> {
    public User getByName(String username) {
        try {
            return userRepository.getByName(username);
        } catch (Throwable e) {
            // says: "Caught: EJBTransactionRolledbackException"
            System.out.println("Caught: " + e.getClass());
            return null;
        }
    }
}

この節は、このメソッド内で発生する可能性のあるすべてのものをキャッチすることを期待してcatch (Throwable e)いますが、明らかに間違っています。私はまだTransactionRolledbackExceptionログに . EJB 例外をキャッチできないのはなぜですか?を読みました。しかし、質問自体に対する本当の答えはありません。

なぜTransactionRolledbackExceptionまだスローされるのですか?どうすればこれを防ぐことができますか? EJBTransactionRolledbackExceptionまた、それは実際に捕らえられていることと何の関係がありますか?

また、メソッド内で例外をキャッチしてgetByNameカスタム例外をスローしようとしましたが、うまくいきませんでした。

4

4 に答える 4

1

ソースコードに従って
UserService = EJB client UserRepository
= EJB クライアントによって呼び出される/呼び出される EJB
単一のトランザクションで。

EJB 3.1 仕様 386 ページからの抜粋

メソッドの条件: Bean メソッドは、呼び出し元のトランザクションのコンテキストで実行されます [注 A]。このケースは、Required、Mandatory、および Supports 属性で発生する可能性があります。

あなたの条件はこれを満たしています

メソッドの例外: その他のすべての例外とエラー

これは基本的に、あなたのケースであるシステム例外がスローされることを意味します(アプリケーション例外はEJBの別のものであり、説明するには多すぎます)

最も重要な部分は、コンテナのアクションに従うことです

コンテナーのアクション
例外またはエラーをログに記録します [注 B]。
トランザクションにロールバックのマークを付けます。
インスタンスを破棄します [注 C]。
クライアントに javax.ejb.EJBTransactionRolledbackException をスローします。[了解しました]

したがって、ソース コード UserService に従って、クライアントは EJBTransactionRolledbackException を受け取ります。理解を深めるために仕様をお読みください。

これがあなたの質問に答えることを願っています。

また、念のため、例外をキャッチしたい場合は、em.createQuery(query).getSingleResult(); の周りに try-catch 句を追加します。UserRepository クラスで。これにより、取得している例外トレースログも削除されます。

于 2013-07-18T13:59:24.543 に答える
0

これは、すべての呼び出しを 1 つのトランザクションに結合するEJB のデフォルトの動作 ( http://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html#REQUIRED ) を使用するために発生します。さて、http://docs.oracle.com/javaee/6/api/javax/ejb/TransactionAttributeType.html#REQUIRES_NEWで TransactionAttribute を使用して、別のトランザクションを強制的に作成できます。どこで開始、参加、または開始/新規トランザクションを行うかを非常に慎重に決定することをお勧めします (たとえば、現在のトランザクションを強制的に保持するか、トランザクションにバインドしないようにすることもできます (これはパフォーマンスに役立ちます))。 .

よろしく、ルアン

于 2013-07-18T13:31:37.723 に答える
0

Sameer Mali の助けを借りて、トランザクションがロールバックされた理由がわかりました。注釈を持つ例外をスローすることで、トレースログを回避できます@ApplicationException。また、 Exception は から継承しない場合がありますが、 からThrowable継承する必要がありExceptionます (これはとにかく合理的です)。コードは次のようになりました。

public User getByName(String username) {
   CriteriaBuilder criteriaBuilder = ...

   try {
       return em.createQuery(query).getSingleResult();
   } catch (NoSuchResultException e){ // Note: this is a System Exception
       throw new NoSuchUserException(username);
   }
}

@ApplicationException
public class NoSuchUserException {
    ...
}
于 2013-08-12T13:51:40.307 に答える