web-dev-qa-db-ja.com

JPAでのフラッシュの正確な目的は何ですか

いくつかの紛らわしい説明:flush();フラッシュは、基盤となる永続ストアをメモリに保持されている永続状態と同期するプロセスです。実行中のトランザクションでテーブルを更新または挿入しますが、これらの変更をコミットしない場合があります。

変更がコミット後にのみデータベースに保持される場合は、コードの途中でフラッシュする理由。

また、フラッシュを実行した後、管理対象オブジェクトに変更が加えられた場合、例外がスローされるか、同期されてから永続化されます。それらが同期された場合は、そもそもなぜフラッシュするのか。

10
Nick Div

理論的には、(JPAのユーザーとして)flush()を呼び出す状況に陥ってはなりません(または非常にまれな状況です)。

フラッシングは、基盤となる永続ストアをメモリに保持されている永続状態と同期するプロセスです。

つまり、flush()では、flush()がデータベースで何も起こらない前に、すべての挿入、更新、削除、またはデータベースで実際に呼び出されるステートメントがすべて実行されます。フラッシュは、トランザクションのコミットまたはある種のデータベース読み取りによって発生します。たとえば、JPQLクエリを実行する場合、データベースから正しい結果を取得するには、flush()を実行する必要があります。しかし、これは非常にわかりやすく、JPA実装によって完全に処理されます。

このフラッシュを自分で制御したい場合があり、flush()で呼び出すことができます。

編集してコメントの質問に答えます:

すべての読み取りでフラッシュが必要なわけではありません。次のシナリオ(1つのトランザクション)を検討してください。

  1. 人を読むPerson p = em.find(Person.class, 234)
  2. 更新者p.setAge(31)
  3. 建物を読むBuilding b = em.find(Building.class, 123
  4. JPQLクエリで建物を読むselect b from Building b where b.id = 123

自動フラッシュは4より前にのみ発生します。これは、Eclipselinkが何を読み取るかを判断できないため、データベース上でその人の年齢が最新である必要があるためです。この読み取りが発生する前に。 3.以前は、Eclipselinkは人の更新が建物に影響を与えないことを知っているため、フラッシュは必要ありません。

楽観的ロックを使用するには、それを実装する必要があります。ここで@Versionアノテーションについて読んでください: https://blogs.Oracle.com/carolmcdonald/entry/jpa_2_0_concurrency_and 。それがないと、エンティティは楽観的ロックを使用せず、「最後の更新が優先されます」。

5
Mathias Begert

トランザクションがコミットされると、エンティティマネージャがそのフラッシュを実行します。場合によっては、コンテナ管理トランザクションでの楽観的ロックの処理のように、特定のロック例外をキャッチして処理するために、flushメソッドを手動で呼び出す必要があります。

2
owenrb