20

以前の質問に関連して、データにアクセスする必要がある可能性のある複数のスレッドがあるため、すべての子オブジェクトが確実に読み込まれるようにしたいと考えています (したがって、遅延読み込みの例外を回避します)。これを行う方法は、クエリ (EJB QL) で「fetch」キーワードを使用することだと理解しています。このような:

select distinct o from Order o left join fetch o.orderLines

Orderのセットを持つクラスを持つモデルを想定しOrderLinesています。

私の質問は、「個別の」キーワードが必要なようです。そうしないと、Orderfor eachが返されるようですOrderLine。私は正しいことをしていますか?

おそらくもっと重要なのは、どんなに深くても、すべての子オブジェクトを取得する方法があるかということです。約10〜15のクラスがあり、サーバーにはすべてをロードする必要があります...それは常に熱心で、特にWebフロントエンドがすべてをロードすることを意味するため、使用を避けてFetchType.EAGERいました-しかし、おそらくそれが行く方法です-それはあなたがすること?以前にこれを試してみたところ、ウェブページが非常に遅くなったことを覚えているようですが、おそらくそれは、2 番目のレベルのキャッシュを使用する必要があるということでしょうか?

4

7 に答える 7

15

注釈を変更することは、IMO の悪い考えです。実行時に遅延に変更できないため。すべてを遅延させ、必要に応じて取得することをお勧めします。

マッピングなしであなたの問題を理解しているかどうかはわかりません。あなたが説明するユースケースに必要なのは、左結合フェッチだけです。もちろん、orderline がその親として注文を持っている場合、すべての orderline の注文が返されます。

于 2008-09-16T11:50:07.303 に答える
8

EJBQL で fetch キーワードを使用するかどうかはわかりません。アノテーションと混同している可能性があります...

FetchType プロパティを関係属性に追加しようとしましたか?

@OneToMany(fetch=FetchType.EAGER)?

見る:

http://java.sun.com/javaee/5/docs/api/javax/persistence/FetchType.html http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

于 2008-09-16T10:53:51.197 に答える
3

結果トランスフォーマーを使用してみましたか? Criteria クエリを使用する場合は、結果トランスフォーマーを適用できます (ただし、ページネーションと結果トランスフォーマーにはいくつかの問題があります)。

Criteria c = ((Session)em.getDelegate()).createCriteria(Order.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.list();

これem.getDelegate()は、休止状態を使用している場合にのみ機能するハックです。

おそらくもっと重要なのは、どんなに深くても、すべての子オブジェクトを取得する方法があるかということです。約10〜15のクラスがあり、サーバーにはすべてをロードする必要があります... FetchType.EAGERの使用を避けていました。これは、常に熱心で、特にWebフロントエンドがすべてをロードすることを意味していたためです-しかし、おそらくそれが進むべき道です-それはあなたがすることですか?以前にこれを試してみたところ、ウェブページが非常に遅くなったことを覚えているようですが、おそらくそれは、2 番目のレベルのキャッシュを使用する必要があるということでしょうか?

それでも興味がある場合は、このスレッドhow to serialize hibernate collectionsで同様の質問に回答しました。

基本的に、Bean を別の Bean にマップするdozerと呼ばれるユーティリティを使用します。これにより、すべての遅延ロードがトリガーされます。ご想像のとおり、すべてのコレクションが熱心にフェッチされている場合、これはうまく機能します。

于 2008-10-22T22:34:23.907 に答える
2

(分離された)基準クエリを使用して、フェッチモードを設定することで、そのようなことができる場合があります。例えば、

Session s = ((HibernateEntityManager) em).getSession().getSessionFactory().openSession();
DetachedCriteria dc = DetachedCriteria.forClass(MyEntity.class).add(Expression.idEq(id));
dc.setFetchMode("innerTable", FetchMode.JOIN);
Criteria c = dc.getExecutableCriteria(s);
MyEntity a = (MyEntity)c.uniqueResult();
于 2008-09-16T18:28:08.360 に答える
0

私が行ったことは、コードをリファクタリングして、オブジェクトのマップをエンティティ マネージャーに保持し、更新する必要があるたびに、オブジェクトの古いエンティティ マネージャーを閉じて、新しいエンティティ マネージャーを開くことです。フェッチなしで上記のクエリを使用したのは、私のニーズには深すぎるためです.OrderLinesで単純な結合プルを実行するだけで、フェッチによりさらに深くなります。

これが必要なオブジェクトはわずか 20 個程度なので、20 個のエンティティ マネージャーを開いていることによるリソースのオーバーヘッドは問題ではないと思います。

また、データベースの作業がメイン スレッド上にあり、エンティティ マネージャーを持つように、作業をやり直しました。

クリス

于 2008-09-16T14:58:00.020 に答える
0

これは ManyToOne 関係でのみ機能し、 @ManyToOne(fetch=FetchType.EAGER) はおそらく適切でしょう。

Jeremy が投稿したリンクで読むことができるように、複数の OneToMany リレーションを積極的にフェッチすることはお勧めできません。このようなフェッチを行うために必要な SQL ステートメントについて考えてみてください...

于 2008-09-16T11:18:03.667 に答える
-4

問題が単に LazyInitializationExceptions である場合は、OpenSessionInViewFilter を追加することで回避できます。
これにより、オブジェクトをビューにロードできますが、速度の問題には役立ちません。

     <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
于 2008-09-16T16:34:22.300 に答える