19

Hibernate についての私の理解は、オブジェクトが DB からロードされると、それらがセッションに追加されるということです。設定に応じて、さまざまな時点でセッションがフラッシュされます。この時点で、変更されたオブジェクトがデータベースに書き込まれます。

Hibernate は、どのオブジェクトが「ダーティ」であり、書き込む必要があるかをどのように判断しますか?

Hibernate によって生成されたプロキシは、フィールドへの割り当てをインターセプトし、オブジェクトをセッションのダーティ リストに追加しますか?

それとも、Hibernate はセッション内の各オブジェクトを見て、それをオブジェクトの元の状態と比較しますか?

それともまったく違うもの?

4

5 に答える 5

24

Hibernateはバイトコード生成(CGLIB)を使用します/使用できるため、セッターを呼び出すとすぐに(またはフィールドafaictに割り当てると)フィールドがダーティであることがわかります。

これにより、そのフィールド/オブジェクトがすぐにダーティとしてマークされますが、フラッシュ中にダーティチェックが必要なオブジェクトの数は減りません。の実装に影響を与えるだけですorg.hibernate.engine.EntityEntry.requiresDirtyCheck()それでも、フィールドごとの比較を行って汚れをチェックします。

上記は、ソースコード(3.2.6GA)の最近のトロールに基づいており、信頼性が追加されています。関心のあるポイントは次のとおりです。

  • SessionImpl.flush()イベントをトリガーしonFlush()ます。
  • SessionImpl.list()イベントautoFlushIfRequired()をトリガーする呼び出し。onAutoFlush()(関心のあるテーブル上)。つまり、クエリはフラッシュを呼び出すことができます。興味深いことに、トランザクションがない場合、フラッシュは発生しません。
  • これらのイベントは両方とも最終的にAbstractFlushingEventListener.flushEverythingToExecutions()はで終わり、(他の興味深い場所の中でも)で終わりflushEntities()ます。
  • source.getPersistenceContext().getEntityEntries()これは、セッション( )の呼び出しですべてのエンティティをループしますDefaultFlushEntityEventListener.onFlushEntity()
  • 最終的にはになりdirtyCheck()ます。このメソッドは、CGLIBダーティフラグに対していくつかの最適化を行いますが、それでもすべてのエンティティをループすることになります。
于 2008-09-17T13:07:12.680 に答える
5

Hibernateは、セッションにロードされる各オブジェクトの状態のスナップショットを取得します。フラッシュ時に、セッション内の各オブジェクトが対応するスナップショットと比較され、どのオブジェクトがダーティであるかが判別されます。SQLステートメントは必要に応じて発行され、スナップショットは(現在はクリーンな)Sessionオブジェクトの状態を反映するように更新されます。

于 2008-09-17T12:35:27.543 に答える
1

org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheckを確認してください。セッション内のすべての要素がこのメソッドに移動し、変更されていないバージョン(キャッシュからのものまたはデータベースからのもの)と比較して、ダーティかどうかを判断します。

于 2008-09-17T12:36:27.557 に答える
1

Hibernate のデフォルトのダーティ チェック メカニズムは、現在アタッチされているエンティティをトラバースし、すべてのプロパティをそれらの初期ロード時間値と照合します。

次の図で、このプロセスをよりよく視覚化できます。

デフォルトの自動ダーティ チェック

于 2014-08-21T11:20:27.713 に答える