5

一意の制約例外をキャッチする必要がある DAO があります。これを行うには、唯一の有効な解決策は、永続化後に EntityManager をフラッシュすることです。そうして初めて、例外を除外する必要がある catch ブロックに入ります。また、DAO メソッドをトランザクション (REQUIRES_NEW) でラップする必要があります。そうしないと、RollBackException が発生します。

私は何か間違ったことをしていますか?

try {
        em.persist(myObject);
        em.flush();
    } catch (PersistenceException ex) {
        if (ex.getCause() != null) {
            String cause = ex.getCause().toString();
            if (cause != null) {
                if (cause.contains("org.hibernate.exception.ConstraintViolationException")) {
                    logger
                            .error("org.hibernate.exception.ConstraintViolationException: possible unique constraint failure on name");
                    throw ex;
                }
            }
        }
    }
4

1 に答える 1

3

私は何か間違ったことをしていますか?

EntityManager#persist()すぐに挿入をトリガーしません (IDENTITY戦略を使用していない限り)。したがって、メモリ内の変更を実際にデータベースに書き込み、制約違反をキャッチする機会を得たい場合は、flush()「手動で」行う必要があります (そうしても厳密には何も保証されませんが、データベースはdeferredを使用するように構成できます)。制約)。

言い換えれば、あなたがやっていることは、IMO の正しい道です。


addNewObject() という @Transactional (必須) を持つサービス メソッドがあります。このメソッドでは、例外をスローする (したがって、トランザクションをロールバックする) 可能性があるいくつかのことが起こります。これらの呼び出しの 1 つは、DAO メソッド addObject への呼び出しです。これは、一意の制約のために失敗する可能性があります。ここでフラッシュすると、一意の違反がなければオブジェクトは永続化されます。ただし、サービス内には、メソッドが例外をスローする原因となる何かが残っている可能性があります。

私はあなたが混乱flushしていると思いますcommit. 外部で何か問題がaddObject発生し、回復不能な例外がスローされた場合 (ただし、同じトランザクション内で)、呼び出しINSERTに対応するステートメントを含め、トランザクション全体がロールバックされpersist()ます。要約すると、flush!= commit.

于 2010-10-19T20:10:58.653 に答える