レコードを更新するとき、session.flush()
をHibernateで使用できます。 flush()
の必要性は何ですか?
セッションをフラッシュすると、HibernateはSession
のインメモリ状態をデータベースと同期させます(つまり、データベースに変更を書き込みます)。デフォルトでは、Hibernateは自動的に変更をフラッシュします:
Session
を明示的にフラッシュできるようにすることで、状況によっては(IDを割り当てたり、セッションのサイズを制御したりするために)より細かい制御が可能になります。
上記の回答で正しく述べられているように、flush()
を呼び出すことで、データベースでSQLコマンドを強制的に休止状態にします。ただし、変更はまだ「コミット」されていないことを理解してください。したがって、フラッシュを実行した後、コミットを実行する前に、(たとえばSQLプロンプトから)DBに直接アクセスし、変更された行を確認すると、変更は表示されません。
これは、2つのSQLコマンドセッションを開くのと同じです。また、1つのセッションで行われた変更は、コミットされるまで他のユーザーには表示されません。
session.flush()
を呼び出すと、ステートメントはデータベースで実行されますが、コミットされません。
セッションオブジェクトでflush()
メソッドを呼び出さず、commitメソッドを呼び出すと、データベースでステートメントを実行してからコミットするという作業を内部で行うとします。
commit=flush+commit
(機能の場合)
したがって、Sessionオブジェクトでメソッドflush()を呼び出すと、コミットは取得されませんが、データベースにヒットしてクエリを実行し、ロールバックも取得すると結論付けます。
コミットするには、Transactionオブジェクトでcommit()を使用します。
セッションをフラッシュすると、現在セッションにあるデータがデータベースにあるデータと同期されます。
Hibernate Webサイトの詳細:
flush()
は便利です。セッションがJDBC呼び出しを実行するタイミングについては絶対に保証されず、実行される順序だけが保証されるためです(flush()
を使用する場合を除く)。
flush
を使用して、トランザクションがコミットされたときではなく、既知の場所で検証制約を強制的に実現および検出できます。 commit
は、一部のフレームワークロジック、宣言的ロジック、コンテナ、またはテンプレートによって暗黙的に呼び出される場合があります。この場合、スローされた例外はキャッチして処理するのが難しい場合があります(コード内で高すぎる可能性があります)。
たとえば、アドレスに一意の制約がある新しいEmailAddressオブジェクトをsave()
する場合、コミットするまでエラーは発生しません。
flush()
を呼び出すと、行が強制的に挿入され、重複がある場合は例外がスローされます。
ただし、例外の後にセッションをロールバックする必要があります。
上記のすべての回答をまとめて、Flush()メソッドとSession.save()を関連付けて、より重要性を高めたいと思います。
Hibernate save()を使用して、エンティティをデータベースに保存できます。トランザクションの外部でこのメソッドを呼び出すことができます。そのため、このメソッドでデータを保存するのは好ましくありません。トランザクションなしでこれを使用し、エンティティ間でカスケードしている場合、セッションをフラッシュしない限り、プライマリエンティティのみが保存されます。
flush():セッションを強制的にフラッシュします。セッションデータをデータベースと同期するために使用されます。
Session.flush()を呼び出すと、ステートメントはデータベースで実行されますが、コミットされません。 session.flush()を呼び出さず、session.commit()を呼び出す場合、内部的にcommit()メソッドがステートメントを実行してコミットします。
したがって、commit()= flush + commit。したがって、session.flush()はデータベース内のステートメントを実行するだけで(コミットは実行しません)、ステートメントはもうメモリにありません。セッションを強制的にフラッシュします。
重要なポイントはほとんどありません。
トランザクション境界外の保存は避ける必要があります。保存しないと、マップされたエンティティが保存されず、データの不整合が発生します。セッションをフラッシュすることを忘れるのは非常に普通です。例外や警告はスローされないからです。デフォルトでは、Hibernateは自動的に変更をフラッシュします:トランザクションがコミットされたときにいくつかのクエリを実行する前)
flush()
メソッドにより、Hibernateはセッションをフラッシュします。 setFlushMode()
メソッドを使用して、セッションにフラッシュモードを使用するようにHibernateを構成できます。現在のセッションのフラッシュモードを取得するには、 getFlushMode()
メソッドを使用できます。セッションがダーティかどうかを確認するには、 isDirty()
メソッドを使用できます。デフォルトでは、Hibernateはセッションのフラッシュを管理します。
ドキュメントに記載されているとおり:
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html
フラッシュ
フラッシュとは、永続コンテキストの状態を基礎となるデータベースと同期させるプロセスです。
EntityManager
およびHibernateSession
は、アプリケーション開発者がエンティティの永続状態を変更できる一連のメソッドを公開します。永続コンテキストは、トランザクションのライトビハインドキャッシュとして機能し、エンティティの状態の変更をキューに入れます。後書きキャッシュと同様に、変更はまずメモリ内に適用され、フラッシュ時にデータベースと同期されます。フラッシュ操作は、すべてのエンティティ状態の変更を取得し、それを
INSERT
、UPDATE
、またはDELETE
ステートメントに変換します。フラッシュ戦略は、現在実行中のHibernateセッションの flushMode で指定されます。 JPAでは2つのフラッシュ戦略(
AUTO
およびCOMMIT
)のみが定義されていますが、Hibernateにはより広範なフラッシュタイプがあります。
ALWAYS
:すべてのクエリの前にセッションをフラッシュします。AUTO
:これはデフォルトのモードであり、必要な場合にのみセッションをフラッシュします。COMMIT
:セッションは、現在のトランザクションがコミットされるまでフラッシュの遅延を試みますが、早すぎるフラッシュもあります。MANUAL
:セッションのフラッシュはアプリケーションに委任されます。アプリケーションは、永続コンテキストの変更を適用するためにSession.flush()
を明示的に呼び出す必要があります。デフォルトでは、Hibernateは次の状況でフラッシュをトリガーする
AUTO
フラッシュモードを使用します。
- トランザクションをコミットする前。
- キューに入れられたエンティティアクションと重複するJPQL/HQLクエリを実行する前。
- 同期が登録されていないネイティブSQLクエリを実行する前。
EntityManager#flush
の呼び出しには副作用があります。生成されたID値(シーケンス値)を持つエンティティタイプに便利に使用されます。このようなIDは、基礎となる永続層との同期時にのみ使用できます。現在のトランザクションが終了する前にこのIDが必要な場合(たとえば、ロギングの目的で)、セッションをフラッシュする必要があります。
この方法では、フラッシュプロセスを呼び出します。このプロセスは、状態の変化を検出し、それぞれのSQLステートメントを実行することにより、データベースの状態をセッションの状態と同期させます。