web-dev-qa-db-ja.com

JPAでの例外処理の改善

エンティティを永続化するときにEJB3/JPAを使用しましたが、DB関連のタスクをどのように管理できるかに満足しています。私の唯一の懸念は、例外処理です。エンティティを保存するときの私のサンプルコードは、常にこのフレーバーで提供されます。私がネットで読んだチュートリアルのほとんどは、例外処理に関係なく、このフレーバーで提供されます。

@Stateless
public class StudentFacade{
    @PersistenceContext(unitName = "MyDBPU")
    private EntityManager em;

    public void save(Student student) {
        em.persist(student);
    }
}

しかし、EJBアプリで例外を処理する最良の方法は何ですか?例外を処理するときの最良の方法は何ですか?

これは他の人が例外を処理する方法ですか?セッションファサードでキャッチブロックを試してみませんか?

@Stateless
public class StudentFacade{
    @PersistenceContext(unitName = "MyDBPU")
    private EntityManager em;

    public void save(Student student) {
        try {
            em.persist(student);
        } catch(Exception e) {
            //log it or do something
        }
    }
}

またはメソッドに例外をスローさせますか?

public void save(Student student) throws Exception {
    em.persist(student);
}

私はまだEJBを学んでいるので、私の理解が正しいかどうかわかりません。ありがとう

17
Mark Estrada

例外処理の考え方は、障害が発生した場合に1つのポイントで何らかのロジックを実行することです。 try catchは、例外を処理する必要がある、または例外を別の例外に変換する必要がある最後のポイントで使用されます。

アプリにアクション、ファサード、永続化などの多くのレイヤーがあるとします

例外の委任この場合、Facadeでスローされた例外は、上記のアクションレイヤーにスローできます。実際には、特定の例外がキャッチされ、適切なエラーメッセージで処理されます。

//This is in Facade Layer
public void save(Student student) throws AppException{
    //exceptions delegated to action layer

    //call to Persist Layer
}

一般的な例外をアプリの例外に変換する永続的に取得すると、sqlExceptionのようなDBExceptionが発生します。この例外は、アクションレイヤーまたはファサードレイヤーにそのまま送信しないでください。そのため、特定の例外をキャッチしてから、新しい例外(アプリケーションのユーザー定義の例外)をスローします。

//This is in Persist Layer
public void save(Student student) throws AppException{
        //converting general exception to AppException and delegating to Facade Layer

        try{
            em.persist(student);//call to DB. This is in Persist Layer
        }catch(Exception e){
            throw new AppException("DB exception", e)
        }
    }

実行中のレイヤー実行中の例外をキャッチし、そこで例外を処理します

  //This is in Action layer
  public void callSave(Student student){
            try{
                //call Facade layer
            }catch(AppException e){
               //Log error and handle
            }
    }
12
Naveen Babu

Em.persistance(...)から取得した例外をメソッドでスローする場合は、そのステートメントをそのtry/catchブロックで囲まないでください(そのブロックにあるすべての例外をキャッチするため)。

この問題に取り組む方法は、レガシーコードがすでに存在するかどうかに関係なく、アプリケーションによって異なります。レガシーコードがある場合は、一貫性を維持するために同じアプローチを使用することをお勧めします(場合によっては最適な速度ではありません)。

それ以外の場合は、例外の「経験則」に従うことをお勧めします。最初に、アクションを実行するために必要なすべての情報がある場合は例外を処理する必要があります。そうでない場合は、他の誰かが処理できるように例外をスローします。 (それらを破棄する場合は、スローできる最も具体的な形式の例外(一般的な例外ではない)を必ずスローしてください)。 JPAを使用する場合の例外の処理は、一般的なJava例外の処理と同じです。

これが「宗教的な会話」を始めることなく、例外についての十分に単純な情報であったことを願っています。

3
Romeo

組み合わせがejbとjpaの場合、すべてのjpa例外はランタイム例外です。

2種類の例外を処理するejb1)アプリケーション例外2)システム例外

アプリケーション例外チェック例外は、基本的にビジネス検証とビジネスルールを使用しています。

システム例外は実行時例外であるため、実行時例外が発生した場合、ejbコンテナーは実行時例外を妨害し、リモート例外として変換します。

例:daoレイヤー内

public void store(Cargo cargo) {
    entityManager.persist(cargo);
}

すべてのjpa例外は、ランタイム例外のみです。

ejbサービスレイヤー内:

public TrackingId bookNewCargo(UnLocode originUnLocode,
        UnLocode destinationUnLocode,
        Date arrivalDeadline) {

    Cargo cargo = new Cargo(trackingId, routeSpecification);
    cargoRepository.store(cargo);
    return cargo.getTrackingId();
}

ejbレイヤーでは、ランタイム例外が発生した場合、ejbコンテナーが干渉し、リモート例外に変換されます。

インターフェイスレイヤー:

 public String register() {

    try {
         String   trackingId = bookingServiceFacade.bookNewCargo(
                    originUnlocode,
                    destinationUnlocode,
                    arrivalDeadline);


    } catch (Exception e) {
        throw new RuntimeException("Error parsing date", e); 
    }

このようにjpa-> ejb-> interface

0
rameshvanka