2012-03-03 10 views
9

私はセッションとトランザクションで混乱しています。私は基本的に両方があることのポイントが何かを見ていないし、どちらかを使用するときは非常に混乱している。Grails:フラッシュされていないセッションとロールバックされたトランザクションの違いは何ですか?

フラッシュされていないセッションとコミットされていないトランザクションの違いは何ですか?

私にはわからないことを尋ねる方法はわかりません...共通のセッションとトランザクションの状況の良い例を示すリソースがあるので、違いを見ることができますか?

答えて

18

Hibernateでのトランザクションは、一般にJDBCでのトランザクションとほぼ同じです。 DataSourceからConnectionを取得すると、デフォルトでautocommit = trueに設定されます。そのため、autocommit = falseに変更されたトランザクションの場合も同様です。そうすれば、更新を行うたびに明示的にコミットされたときにのみ、データベースに変更が加えられます。

HibernateのSessionはいくつかのことを行いますが、この場合、その機能は第1レベルのキャッシュと同じです。パフォーマンスのために、キャッシュ内の変更をキューに入れ、必要に応じてデータベースにプッシュするという目的で、「トランザクションwritebehind」という概念を使用します。たとえば、永続的なインスタンスを取得し、複雑なマルチメソッドワークフローで変更する場合、各メソッドは何も変更しないか、複数の場合がありますが、Hibernateは更新のSQL文を1つだけ必要とします。これはトランザクションで実行しているかどうかに関係なく、常に発生します。

セッションキャッシュとアクティブトランザクションが一緒になって、アクティブなトランザクション中にフラッシュされます。 Hibernateは変更をフラッシュするためにできるだけ長く待つので、トランザクション中でなくてもフラッシュすると、変更はすぐにデータベースに永続的になります。つまり、データベースの書き込み回数を減らすためのパフォーマンスの最適化です。しかし、トランザクション中にセッションをフラッシュする場合は、変更をデータベースにプッシュします。ただし、データベースはトランザクション・キュー内の変更を保持します。したがって、データベースに入っていても、トランザクションをコミットするまで他の接続には表示されません。

理想的には、フラッシュは一切発生せず、トランザクションコミットによってコミット前にフラッシュがトリガされ、データベースに移動してコミットされていない変更を他の呼び出し元には見えないようにする回数が最小限に抑えられます。しかし、必要な回数だけフラッシュすることができます。

Hibernateを自動的にフラッシュする原因は、クエリです。私が言ったように、永続的なインスタンスを(削除しても)多くの変更を加えることができ、セッションキャッシュにキューイングされます。しかし、クエリ(動的ファインダ、基準、HQLなど)を実行すると、Hibernateはキューに入れられた変更がクエリに影響するかどうかを知ることができません。したがって、すべてのクエリが一貫していることを確認するのは悲観的なことです。データベースは、照会にフラッシュされたがコミットされていないデータを使用し、予期した結果を返します。これは、カスタムドメインクラスバリデーターでクエリを実行するときにwithNewSessionメソッドを使用することを推奨する理由で、奇妙な動作を引き起こす可能性がある検証中に現在のセッションがフラッシュされないようにするためです。

関連する問題