Hibernateでのsession.flush()の使用とは


110

レコードを更新するときにsession.flush()、Hibernate を使用できます。何が必要ですflush()か?

回答:


138

セッションをフラッシュすると、Hibernateはのメモリ内状態をSessionデータベースと同期します(つまり、変更をデータベースに書き込みます)。デフォルトでは、Hibernateは変更を自動的にフラッシュします。

  • クエリを実行する前
  • トランザクションがコミットされたとき

を明示的にフラッシュSessionできるようにすると、状況によっては必要になる可能性のある細かい制御が可能になります(IDの割り当て、セッションのサイズの制御など)。


8
この回答はデフォルトの休止状態の動作を説明していることに注意してください。フラッシュの動作は、[フラッシュモード]設定で変更できます。詳細はdocs.jboss.org/hibernate/orm/3.5/api/org/hibernate/…(バージョン3.5)にあります。
SteveT 2012年

1
私はあなたが言っていることを正確に言っているドキュメントを見つけましたが、何が優先されるかということは疑問です1)コードid = session.save(obj);を使用してオブジェクトを保存しているクラスがあり、トランザクションが次の行でコミットされていますが、objが保存されていませんDBに、なぜ?2)session.save(obj);with commitを使用してobjを保存し、戻るときに使用しreturn obj.getprimaryID();ましたこの場合、objはDBに保存されます。では、なぜこの動作が起こっているのでしょうか?
アモグ2015

74

上記の回答で正しく述べたように、呼び出すflush()ことにより、HibernateはデータベースでSQLコマンドを実行します。ただし、変更はまだ「コミット」されていないことを理解してください。したがって、フラッシュを実行した後、コミットを実行する前に、DBに直接(たとえば、SQLプロンプトから)アクセスし、変更された行を確認すると、変更は表示されません。

これは、2つのSQLコマンドセッションを開くのと同じです。また、1つのセッションで行われた変更は、コミットされるまで他のユーザーには表示されません。


12
まあ-変更はわずかに見えることがあります。たとえば、コミットされていない行は、挿入されているがコミットされていない行にロックを作成し、トランザクションがコミットまたはロールバックされるまで、同じ行が別のセッションによって挿入されるのを遅らせることができます。したがって、完全に見えなくなるわけではありません。
rghome 2015年

2
私はネット上でサーフィンをしてきましたが、これが最終的に私がそれを手に入れた答えです。ありがとう。
Siddhartha、2016年

commit()が最後にフラッシュを実行する場合、.flush()をforループに入れることの使用は何ですか?
エイルドサ

@Kaushik Leleフラッシュ後にデータが表示されない場合のflush()のポイントは何ですか?これが役立ついくつかのより細かい使用例について詳しく説明できますか?
java_geek

28

session.flush()ステートメントを呼び出すとデータベースで実行されますが、コミットされないことがわかります。

我々は呼んでいないと仮定しflush()たセッションオブジェクトのメソッドを、我々は法を犯す呼び出す場合、それは内部的にデータベース上の文を実行してからコミットの作業を行います。

commit=flush+commit (機能の場合)

したがって、Sessionオブジェクトでメソッドflush()を呼び出すと、コミットは行われませんが、データベースにヒットしてクエリを実行し、ロールバックも取得すると結論付けます。

コミットするには、Transactionオブジェクトでcommit()を使用します。


フラッシュの必要性について詳細を教えてください。
java_geek

14

セッションをフラッシュすると、現在セッション内にあるデータがデータベース内のデータと同期されます。

Hibernate Webサイトの詳細:

flush()セッションがいつJDBC呼び出しを実行するかについての保証はまったくなく、使用する場合を除いて、それらが実行される順序のみが保証されるため、便利ですflush()


ユーザーがシーケンスについて心配する必要があるシナリオを提供できますか?hibernateの使用は、DB関連のものをユーザーに対して透過的にすることです。「コミット」すると、自動的にフラッシュが行われます。フラッシュするがコミットしないシナリオは何ですか?
Kaushik Lele 2015

1
あなたはこの質問を参照することができ@KaushikLele stackoverflow.com/questions/37382872/...
GMsoF

10

を使用flushして、トランザクションがコミットされたときではなく、既知の場所で検証制約を実現および検出することができます。commit一部のフレームワークロジック、宣言型ロジック、コンテナ、またはテンプレートによって暗黙的に呼び出される可能性があります。この場合、スローされた例外はキャッチして処理することが難しい場合があります(コードで高すぎる可能性があります)。

たとえばsave()、アドレスに一意の制約がある新しいEmailAddressオブジェクトの場合、コミットするまでエラーは発生しません。

呼び出すとflush()強制的に行が挿入され、重複がある場合は例外がスローされます。

ただし、例外の後でセッションをロールバックする必要があります。


4

上記のすべての回答をまとめて、Flush()メソッドをSession.save()と関連付けて、より重要なものにしたいと思います。

Hibernate save()を使用して、エンティティをデータベースに保存できます。このメソッドはトランザクションの外部で呼び出すことができるため、データを保存するためにこのメソッドを使用したくありません。トランザクションなしでこれを使用し、エンティティ間のカスケードがある場合、セッションをフラッシュしない限り、プライマリエンティティのみが保存されます。

flush():セッションを強制的にフラッシュします。セッションデータをデータベースと同期するために使用されます。

session.flush()を呼び出すと、ステートメントはデータベースで実行されますが、コミットされません。session.flush()を呼び出さず、session.commit()を呼び出す場合、内部的にcommit()メソッドがステートメントを実行してコミットします。

つまり、commit()= flush + commitです。そのため、session.flush()はデータベース内のステートメントを実行するだけで(コミットはしません)、ステートメントはもうメモリ内にありません。セッションを強制的にフラッシュするだけです。

いくつかの重要なポイント:

トランザクション境界の外に保存することは避けてください。そうしないと、マップされたエンティティが保存されず、データの不整合が発生します。例外や警告をスローしないため、セッションのフラッシュを忘れることはごく普通のことです。デフォルトでは、Hibernateは変更を自動的にフラッシュします。トランザクションがコミットされたときにクエリを実行する前に、明示的にセッションをフラッシュできるようにすると、状況によっては(IDを割り当てたり、セッションのサイズを制御したりするために)より細かい制御が必要になる場合があります)


3

このflush() メソッドにより、Hibernateはセッションをフラッシュします。setFlushMode()メソッドを使用して、セッションでフラッシュモードを使用するようにHibernateを構成できます。現在のセッションのフラッシュモードを取得するには、getFlushMode()メソッドを使用できます。セッションがダーティかどうかを確認するには、isDirty()メソッドを使用します。デフォルトでは、Hibernateはセッションのフラッシュを管理します。

ドキュメントに記載されているように:

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

フラッシング

フラッシュは、永続化コンテキストの状態を基礎となるデータベースと同期させるプロセスです。EntityManagerそしてHibernateはSession、アプリケーション開発者は、エンティティの永続状態を変更することができ、それを通してメソッドのセットを公開します。

永続化コンテキストは、トランザクションのライトビハインドキャッシュとして機能し、エンティティの状態変化をキューに入れます。後書きキャッシュと同様に、変更は最初にメモリー内に適用され、フラッシュ時にデータベースと同期されます。フラッシュ操作は、すべてのエンティティの状態変化を受け取りINSERT、それを、UPDATEまたはDELETEステートメントに変換します。

フラッシュ戦略は、現在実行中のHibernateセッションのflushModeによって指定されます。JPAが定義しているフラッシュ戦略は2つ(AUTOCOMMIT)だけですが、Hibernateのフラッシュタイプのスペクトルははるかに広くなっています。

  • ALWAYS:すべてのクエリの前にセッションをフラッシュします。
  • AUTO:これはデフォルトのモードであり、必要な場合にのみセッションをフラッシュします。
  • COMMIT:セッションは、現在のトランザクションがコミットされるまでフラッシュを遅らせようとしますが、時期尚早にフラッシュする可能性もあります。
  • MANUAL:セッションのフラッシュはアプリケーションに委任されます。アプリケーションSession.flush()は永続化コンテキストの変更を適用するために明示的に呼び出す必要があります。

デフォルトでは、HibernateはAUTO次の状況でフラッシュをトリガーするフラッシュモードを使用します。

  • トランザクションをコミットする前。
  • キューに入れられたエンティティアクションと重複するJPQL / HQLクエリを実行する前。
  • 同期が登録されていないネイティブSQLクエリを実行する前。

1

呼び出しにEntityManager#flush副作用があります。これは、生成されたID値(シーケンス値)を持つエンティティタイプに便利に使用されます。このようなIDは、基盤となる永続化レイヤーとの同期時にのみ使用できます。現在のトランザクションが終了する前にこのIDが必要な場合(ログの目的など)、セッションをフラッシュする必要があります。


0

この方法では、フラッシュプロセスを呼び出します。このプロセスでは、状態の変化を検出してそれぞれのSQLステートメントを実行することにより、データベースの状態をセッションの状態と同期させます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.