4

私は、さまざまな集合ルートのセットを持つリッチ オブジェクト モデルを持つプロジェクトに取り組んでいます。

Castleスタック (モノレールから ActiveRecord を使用した nHibernate まで) を使用しています。

集約ルートを遅延としてマークし[ActiveRecord(Lazy = true)]、オブジェクト グラフを熱心にフェッチするために、リポジトリで「熱心な」ルーチンをカスタマイズしました。HQL を使用して、ルートの子コレクションから熱心なフェッチを定義します。

たとえば、集約ルート (および遅延ロードとマークされている)の場合、完全なグラフのエンティティをAccount熱心にフェッチします。Account .. Order .. Product

したがって、これまでのところ驚くことはありません(うまくいけば)。

上記の例で、Product もマークされている場合[ActiveRecord(Lazy = true)]、HQL の熱心なフェッチ ディレクティブが停止しているように見えます。

遅延ロードされた子オブジェクトの熱心なフェッチを強制する方法を知っている人はいますか??

乾杯イアン

更新

ここに hql の例があります。以下の「me.yahoo.com/../1」の例を使用すると、IMuliQuery を使用して、多対多の関係をフェッチするときに N+1 の依存関係を解決しています。また、多対多のマッピング クラスを明示的に使用しています。その結果、本社は次のようになります。

from Account a 'm eager loading the graph
inner join fetch a.AccountsOrders ao 
inner join fetch ao.Order
from Account a 'm eager loading the graph
inner join fetch a.AccountAddresses aa
inner join fetch aa.Address ad
where a.ID = ?

...これにより、2 つの sql ステートメントが実行され、必要な最小限の行セットが返されます。これを単一のオブジェクト グラフに解決できます。良い。

しかし...たとえば、Address遅延ロードとマークされた(そしてOrderそうではなかった)場合、アクセスOrderはそれ以上のSQLステートメントをトリガーしませんAddressが、どちらも熱心にロードされているにもかかわらず、アクセスは実行します。

Addressでは、上記の遅延ロードされたエンティティが上記のステートメントによって熱心にフェッチされないのはなぜでしょうか?

4

3 に答える 3

1

Account.Order.Product エンティティで "inner join fetch" を実行します。したがって、このようなものの代わりに(おそらくすでに持っているものです):

"from Account a inner join fetch a.Order where a.ID = ?"

Order.Product も取得するように指示します。

"from Account a inner join fetch a.Order inner join fetch a.Order.Product where a.ID = ?"
于 2008-12-19T19:55:41.717 に答える
0

なぜ熱心な行動が必要なのですか?

ActiveRecord のすべての Relationship 属性には、関連オブジェクトを遅延ロードするように ActiveRecord に指示する 'Lazy=' パラメータがあります。BelongsTo を除くすべて。BelongsTo は、依存オブジェクトの ActiveRecord 属性に Lazy=true が含まれているかどうかをチェックし、選択または結合を実行する代わりに、オブジェクトのプロキシを作成します。

遅延読み込みを機能させるには、クラス インスタンスのすべてのメソッドとプロパティを仮想としてマークする必要があります。これにより、ActiveRecord は動的プロキシ クラスを構築できます。

パフォーマンスのために完全なグラフを取得することは良い考えのように思えるかもしれませんが、実際にはおそらく遅くなります。私には 3 つの正当な理由があります。

1.) BelongsTo には、関連するオブジェクトを取得する方法を定義する Fetch オプションがあります。FetchEnum.Join は、AR に Join の使用を強制します。FetchEnum。Select は、AR がオブジェクトごとに別々の select ステートメントを使用することを強制します。結合が遅く、個々の選択に切り替えることでパフォーマンスが 10 倍向上しました。Lazy=true + FetchEnum.Select とeager の間のクライアント コードに効果的な違いはありません。

2.) NHibernate はキャッシングを行います。オブジェクトがすでにセッションまたはレベル 2 キャッシュにキャッシュされている場合は、そこからロードして余分な作業を避けることができます。

3.) オブジェクト グラフの一部を参照しなかった場合、遅延読み込みのメリットを逃してしまいます。この場合も、必要以上の作業を行うことになります。

于 2009-02-13T20:41:55.910 に答える