汚れたオブジェクトを含まないエンティティ・マネージャからトランザクションをコミットするとどうなりますか? COMMITコマンドがDBに送信されないことはありますか?アンラップされた接続によってJPAコミットの変更が行われる
私はいくつかのテストケースが今や失敗していて、合理的な理由がないままでした。いくつかの調査の後、ここで私がここで確認したい理論があります。
私は小さなテストフレームワークを持っており、各テストのDB上のデータを準備しています。固定具は、JPA(休止状態)を使用してDBにオブジェクトを格納するような方法を使用します。したがって
public <R> R doInTransaction(final Function<EntityManager, R> whatToDo) {
final EntityManager em = emf.createEntityManager();
final R result;
try {
try {
em.getTransaction().begin();
result = whatToDo.apply(em);
em.getTransaction().commit();
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
}
} finally {
em.close();
}
return result;
}
を、固定具は、オブジェクトが永続化さwhatToDo関数を渡し、このメソッドを呼び出し、メソッドは、渡された関数の周りにトランザクションをラップ。失敗したテストケースでは、ストアドプロシージャを使用するレガシーコードに依存するフィクスチャを使用し、JDBCを介してオブジェクトを直接格納しています。 e。によって管理されるいかなるJPA済オブジェクトが存在しないように、私の理論は、JPAは、このような状況ですぐにコミットされていないということです
em.unwrap(Session.class).doWork(connection -> {
// stored procedures are called here directly over JDBC
});
:代わりにem.persist()
を使用して、私はストアドプロシージャを呼び出すために渡された関数で次のように使用しますEntityManager。その結果、実際のコミットは後でのみ発生します。 e。私のテストの主張の後に、テストは失敗します。それは可能性が?
EntityManagerから接続を「アンラッピングする」ときのHibernateのトランザクション動作は何ですか?
em.getTransaction().commit()
の前にem.flush()
を追加しましたが、これは役に立ったようですが、これが問題を解決するとはまだ100%自信がありません。誰かが確認できますか?
永続性ハンドラを混合してマッチングするときは注意が必要です。 Hibernateは、何が汚いのか、何がないのかのキャッシュを維持します。休止状態以外のものを更新している場合、キャッシュされたエンティティのバージョンがまだ有効であると思うので、休止状態がdbと同期しなくなり、更新が破棄される可能性があります。私はこのような問題を数年前に実行していましたが、正しく覚えていれば、動作を阻止するために休止状態でキャッシュを無効にしました。 – Stephan
私はHibernateでキャッシングの不思議な世界に入りたくないのです。:) 'em.flush()がここで仕事をするなら、これで十分です。 – Alex
テスト環境にいる場合、em.flush()を試してみることができます。並んでいる人数が並外れていると予想されない場合は、休止状態でキャッシュを無効にして、データベース内のキャッシュが大量の作業を処理できるようにする必要があります。これは別のことですが、dbのデフォルトのキャッシングは、hibernateのデフォルトキャッシングを妨げる可能性があります。引き続き問題が発生する場合は、休止状態のキャッシュをオフにすることを強くお勧めします。 – Stephan