2012-03-20 12 views
0

エンティティとして表されるディレクトリ・タイプの構造を持っています。Hibernateの再帰的フェッチ・ジョインはすべての子を再帰的にフェッチしません

ディレクトリエンティティには、ファイルエンティティのコレクションとディレクトリエンティティのコレクションがあります。

私はルートディレクトリを取得し、すべてのディレクトリとそこにファイルを '事前にロードする'。

私がしようとしています:

String queryString = "SELECT DISTINCT d FROM " + 
    Directory.class.getSimpleName() + 
    " d LEFT JOIN FETCH d.files LEFT JOIN FETCH d.directories child LEFT JOIN FETCH child.files LEFT JOIN FETCH child.directories WHERE f.root = :isRoot); 
Query query = em.createQuery(queryString); 
query.setParameter("isRoot", true); 

Directory dir = (Directory) query.getSingleResult(); 

問合せは、それだけですべてを読み込む事前ありません動作します。私はすべてのルートディレクトリとルートファイルを取得しますが、サブディレクトリに移動してファイルを取得すると、クエリが作成されます。 I.再帰が機能していないようです。

私はまた、JOIN FETCH(これは私が内部結合フェッチをすると思う)を運のない状態で試しました。

アイデア?

+0

それは確か行います!ドキュメントを読んだ場合、状態は次のとおりです。fetch joinは、関連するオブジェクトをwhere句(または他の句)で使用しないでください。通常、エイリアスを割り当てる必要はありません。関連オブジェクトも照会結果に直接戻されません。代わりに、親オブジェクトを介してアクセスすることができます。 cat.mate はcat.kittensをフェッチ参加左内側 フェッチ参加する猫のように猫から 子 がもしそうならchild.kittensに – lostintranslation

+0

をフェッチ左結合:あなたコレクションを再帰的に結合フェッチする場合は、エイリアスを必要とするかもしれない唯一の理由は、その記事の中で私が探しているのは、あなたが探している再帰的なクエリを書くことはできませんが、HQLを使って階層を熱心に取り出すことは可能です。これを行うと、少なくとも、各レベルのデータベースにぶつかることなく、ツリー内を歩き回ることができます。 ノードnからnを選択してください 左に結合フェッチn.Children ' – lostintranslation

+0

私は修正しました=) – esaj

答えて

2

に役立ちます。そのため、「ノードnからnを選択してフェッチn.Childrenを残しておけば」、単一のツリーが必要な間にすべてのツリーをメモリにフェッチしました。 WHERE句を追加すると再帰が壊れてしまいます。

だから、私はDAO内部の再帰ヘルパーを使用:

private Node fetchChildren(Node parent) { 
    Hibernate.initialize(parent.getChildren()); 
    for (Node child : parent.getChildren()) { 
     fetchChildren(child); 
    } 
    return parent; 
} 
0

エンティティ間のフェッチを熱心に定義しましたか(@OneToMany(fetch = FetchType.EAGER))?

問題の初期フェッチの問題(more detailed answer)を解決できるようです。

esaj comment link answerには、再帰を処理する方法が含まれています。

希望これは、複数の独立した木を、私は同じ問題に直面していましたが、私の場合には、単一のテーブルが格納

+1

ありがとうございますが、それは私が望むものではありません。その理由は、デフォルトの動作を怠惰にして、その動作をオーバーライドするクエリだけが熱心に再帰的にフェッチする必要があるためです。 Hibernateのドキュメントは、このタイプの動作をサポートしていると言います。 – lostintranslation