22

問題は、この特定の例で GORM が内部結合ではなく左結合を生成するようにするにはどうすればよいかということです。

テストベッド:

クラス A、B、および C が与えられた場合:

class A{
    B someObject
}

class B{
    C importantObject
}

class C{
    boolean interestingFlag
}

次のような A クラスのすべての要素をリストしたいと思います。

  • BC オブジェクトが null である OR
  • BC オブジェクトの InterestingFlag 値が false である

私がこれまでに試したこと:

このアプローチは、BC が null である A の正しいリスト (条件 2 がコメント アウトされている) または BCinterestingFlag = false である A の正しいリスト (条件 1 がコメント アウトされているかどうかに関係なく) を生成します。両方の条件がコメント化されていない場合、ABCinterestingFlag = false (ABC = null 条件は無視される) の要素のリストのみが返されます。

// approach 1 (conditional 1 is ignored)
def result = A.withCriteria{
    someObject{
        or{
            isNull('importantObject') // conditional 1, works well when conditional 2 is commented out
            importantObject{
                eq('interestingFlag', false) // conditional 2, works well alone, discards conditional 1 when both of them are uncommented
            }
        }  
    } 
}

編集:コメントで要求されたように、休止状態で生成されたSQLを貼り付けています:

Hibernate: select this_.id as id1_2_, this_.version as version1_2_, 
this_.some_object_id as some3_1_2_, someobject1_.id as id2_0_, 
someobject1_.version as version2_0_, someobject1_.important_object_id as 
important3_2_0_, importanto2_.id as id0_1_, importanto2_.version as version0_1_, 
importanto2_.interesting_flag as interest3_0_1_ from a this_ 
inner join b someobject1_ on this_.some_object_id=someobject1_.id 
inner join c importanto2_ on someobject1_.important_object_id=importanto2_.id 
where ((someobject1_.important_object_id is null or (importanto2_.interesting_flag=?)))

pgAdminクエリツールに直接コピーして貼り付けると、いくつかの変更が加えられました(内部結合が左結合に変更され、interestingFlag = "false"パラメータが提供されました)。偽物)

Hibernate: select this_.id as id1_2_, this_.version as version1_2_, 
this_.some_object_id as some3_1_2_, someobject1_.id as id2_0_, 
someobject1_.version as version2_0_, someobject1_.important_object_id as 
important3_2_0_, importanto2_.id as id0_1_, importanto2_.version as version0_1_, 
importanto2_.interesting_flag as interest3_0_1_ from a this_ 
left join b someobject1_ on this_.some_object_id=someobject1_.id 
left join c importanto2_ on someobject1_.important_object_id=importanto2_.id 
where ((someobject1_.important_object_id is null or (importanto2_.interesting_flag=false)))
4

3 に答える 3

43

テスト済みの実用的なソリューション:

    def result = A.withCriteria{
        createAlias('someObject', 'so', CriteriaSpecification.LEFT_JOIN)
        createAlias('so.importantObject', 'imp', CriteriaSpecification.LEFT_JOIN)
        or {
            isNull('so.importantObject')
            eq('imp.interestingFlag', false)
        } 

    }

コメントで提案されているソリューションの更新:

    def result = A.withCriteria{
        createAlias('someObject', 'so', JoinType.LEFT_OUTER_JOIN)
        createAlias('so.importantObject', 'imp', JoinType.LEFT_OUTER_JOIN)
        or {
            isNull('so.importantObject')
            eq('imp.interestingFlag', false)
        } 

    }
于 2013-06-17T11:00:39.613 に答える