3

更新: 2.0.1 のこの Grails バグに関連している可能性があります: http://comments.gmane.org/gmane.comp.lang.groovy.grails.user/125400

更新 2 : これは私に最も近いものですが、ページネーションは機能しません。この場合、すべての A が返され、それぞれに B のリストがあり、各 B にその C が含まれています。offset と max を追加するとすぐに、問題が発生します。たとえば、この場合、10 個の A は返されません。おそらく、1 つの A と 9 つの B が返されます。

def results = A.list([fetch:[bees: "eager"], offset: 0, max: 10]);

問題: すべての A、それらに関連付けられた B、および B に関連付けられた C を 1 つのクエリでロードしたいと考えています。すべての A と関連する B を 1 つのクエリで取得するのは非常に簡単です。同じ単一のクエリの一部として、すべての B の C も読み込む方法がわかりません。設計上、B をロードするときは常に C が必要になるため、B -> C からのデフォルトのマッピングは積極的である必要があります。このマッピングを設定すると問題が解決すると思いました。

class A {
    static hasMany = [
            bees:  B,
    ]
}

class B {
    C c;

    static belongsTo = [a: A]

    // also tried this and every possible combination
    //static fetchMode = [c: 'eager']

    static mapping = {
        c fetch: 'join'
        // c lazy: 'false'
    }
}

class C {
    String someField;
}

これが私のクエリです:

def results = A.executeQuery("from A a left join fetch a.bees",
                     [max: pageSize, offset: offset]);

結果を繰り返し処理すると、次のようになります。

for (A a in results) {
   for (B b in a.bees) {
      println "B: " + b; // this is OK, B is already loaded
      println "B's C: " + b.c.someField; // C not loaded
   }
}

結果を反復処理すると、bcsomeField の行により、各 B ごとに「選択」が実行されます。これは悪いことです。可能であればこれを避けたいと思います。ルックアップ マップで 2 番目のクエリを使用するソリューションを回答として投稿しましたが、もっと良い方法があるはずです。

「Update 2」に投稿したクエリは、私を非常に近づけます。実際、ページネーション (オフセット/最大) を使用するまでは問題なく動作します。Grails のユーザー ガイドでは、「fetch: 'join' はオフセット/最大値を使用したクエリで問題を引き起こす可能性がありますが、詳細には触れていません。注: このクエリを機能させるには、前述のように休止状態のクエリ キャッシュを無効にする必要がありました。 Grails 2.0.1 のバグによる「アップデート 1」。

何か案は?

4

2 に答える 2

0

Grails のドキュメントによると、GORM はデフォルトで遅延読み込みを行います。ドキュメントへのリンクは次のとおりですhttp://grails.org/doc/1.1/guide/5.%20Object%20Relational%20Mapping%20(GORM).html

私はあなたがここで何を求めているのか明確ではありません

于 2012-05-11T00:57:26.067 に答える
0

回避策は、すべての A とそれに関連する B を単純に取得することです。

それができたら、クエリを実行せずにすべての C の ID を取得できます。

def cIds = [] as Set;

for (A a : results) {
    for (B b : a.bees) {
        // Note: getCId() is a special method which does not cause a query
        cIds.add(b.getCId());
    }
}

すべての C ID を取得したら、2 番目のクエリを使用してデータベースからこれらを取得し、後で検索できるようにマップに格納できます。

def cMap = [:]
def cees = C.getAll(cIds.toList());
for (C c : cees) {
    cMap[c.id] = c;
}

これで、元の結果セットを繰り返し処理して、C のフィールドを出力できます。

for (A a : results) {
    for (B b : a.bees) {
        println "The meaning of life is " + cMap[b.getCId()].someField;
    }
}

合計クエリ = 2 (元の左結合用に 1 つ、すべての C を取得するための 2 つ目)

誰かがより良い解決策を持っている場合は、投稿してください。

于 2012-05-10T22:54:16.573 に答える