Hibernate ISession フラッシュ:いつ、どこで、そしてその理由を教えてください。
-
09-06-2019 - |
質問
私を完全に混乱させることの 1 つは、 session.Flush
と合わせて session.Commit
, 、 そして session.Close
.
時々 session.Close
たとえば、必要なすべての変更をコミットします。トランザクションがある場合、または複数の作成/更新/削除を伴う作業単位がある場合は、エラーが発生した場合にロールバックを選択できるように、コミットを使用する必要があることはわかっています。
でも時々、その背後にある論理に本当に困惑することがあります session.Flush
. 。私はあなたが持っている例を見てきました session.SaveOrUpdate()
その後にフラッシュが続きますが、フラッシュを削除すると、とにかく正常に動作します。時々、Flush ステートメントでセッションがタイムアウトしたことを示すエラーが発生することがありますが、それを削除することでそのエラーが発生しないようにできました。
フラッシュをどこで、いつ使用するかについて適切なガイドラインを持っている人はいますか?これについて NHibernate のドキュメントを確認しましたが、まだ単純な答えが見つかりません。
解決
簡単に言うと:
- 常にトランザクションを使用する
- 使用しないでください
Close()
, 代わりに、呼び出しをラップします。ISession
の中にusing
声明または ISession のライフサイクルを別の場所で管理する.
から 文書:
時々、
ISession
ADO.NET 接続の状態とメモリに保持されているオブジェクトの状態を同期するために必要な SQL ステートメントを実行します。このプロセスであるフラッシュは、デフォルトで次の時点で発生します。
- いくつかの呼び出しから
Find()
またはEnumerable()
- から
NHibernate.ITransaction.Commit()
- から
ISession.Flush()
SQL ステートメントは次の順序で発行されます。
- すべてのエンティティの挿入。対応するオブジェクトが保存された順序と同じです。
ISession.Save()
- すべてのエンティティの更新
- すべてのコレクションの削除
- すべてのコレクション要素の削除、更新、挿入
- すべてのコレクションの挿入
- すべてのエンティティの削除。対応するオブジェクトが次の方法で削除されたのと同じ順序で行われます。
ISession.Delete()
(例外として、ネイティブ ID 生成を使用するオブジェクトは保存時に挿入されます。)
明示的に指定した場合を除いて、
Flush()
, 、セッションが ADO.NET 呼び出しをいつ実行するかについてはまったく保証がなく、実行される順序のみが保証されます。. 。ただし、Hibernate は次のことを保証します。ISession.Find(..)
メソッドが古いデータを返すことはありません。また、間違ったデータを返すこともありません。フラッシュの発生頻度を下げるようにデフォルトの動作を変更することができます。の
FlushMode
クラスは 3 つの異なるモードを定義します。コミット時のみフラッシュします (そして NHibernate が実行されるときのみ)ITransaction
API が使用されます)、説明されたルーチンを使用して自動的にフラッシュするか、そうでない限りフラッシュしません。Flush()
明示的に呼び出されます。最後のモードは、長時間実行される作業単位に役立ちます。ISession
長時間開いたまま切断されたままになります。
...
こちらも参照してください このセクション:
セッションの終了には、次の 4 つの異なるフェーズが含まれます。
- セッションをフラッシュする
- トランザクションをコミットする
- セッションを閉じる
- 例外を処理する
セッションのフラッシュ
たまたま使用している場合は、
ITransaction
API の場合、この手順について心配する必要はありません。これは、トランザクションがコミットされるときに暗黙的に実行されます。それ以外の場合は電話する必要がありますISession.Flush()
すべての変更がデータベースと同期されていることを確認します。データベーストランザクションのコミット
NHibernate ITransaction API を使用している場合、これは次のようになります。
tx.Commit(); // flush the session and commit the transaction
ADO.NET トランザクションを自分で管理している場合は、手動で行う必要があります。
Commit()
ADO.NET トランザクション。sess.Flush(); currentTransaction.Commit();
変更をコミットしない場合は、次のようにします。
tx.Rollback(); // rollback the transaction
または:
currentTransaction.Rollback();
トランザクションをロールバックする場合は、Hibernate の内部状態が一貫していることを確認するために、現在のセッションを直ちに閉じて破棄する必要があります。
Iセッションを閉じる
への電話
ISession.Close()
セッションの終了を示します。Close() の主な意味は、ADO.NET 接続がセッションによって放棄されることです。tx.Commit(); sess.Close(); sess.Flush(); currentTransaction.Commit(); sess.Close();
独自の接続を提供した場合、
Close()
はその参照を返すので、手動で閉じるか、プールに返すことができます。さもないとClose()
プールに返します。
他のヒント
NHibernate 2.0 以降、DB 操作にはトランザクションが必要になります。したがって、 ITransaction.Commit()
呼び出しは必要なフラッシュを処理します。何らかの理由で NHibernate トランザクションを使用していない場合、セッションは自動フラッシュされません。
ISession は、ADO.NET 接続の状態とメモリに保持されているオブジェクトの状態を同期するために必要な SQL ステートメントを実行することがあります。
そしていつも使うのは
using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}
変更がコミットされた後、この変更をデータベースに保存するために、transaction.Commit(); を使用します。
ここでは、session.Flush() がないと失敗するコードの 2 つの例を示します。
http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html
この最後に、ID 挿入をオンに設定し、エンティティを保存してフラッシュし、ID 挿入をオフに設定するコードのセクションが表示されます。このフラッシュがないと、ID 挿入のオンとオフを設定してからエンティティを保存しているようです。
Flush() を使用すると、何が起こっているかをより詳細に制御できるようになりました。
別の例を次に示します。
TransactionScope 内で NServiceBus メッセージを送信する
これの理由は完全には理解できませんが、Flush() によりエラーの発生は防止されました。