2016-06-21 65 views
0

標題說明了問題本身。我有這個Grails Domain類。當評估子屬性時,Hibernate在何處或語句不起作用

class IonicBond { 
    ... 

    static hasMany = [ 
     typeIIs: TypeII, 
     typeRs: TypeR, 
    ] 

    static constraints = { 
     typeIIs nullable: true 
     typeRs nullable: true 
    } 
} 

我需要根據它的特性hasMany要查詢的IonicBond實例。事情是這樣的:

ArrayList<IonicBond> list = IonicBond.createCriteria().list { 
    or { 
     typeIIs { 
      eq("classCode", "WD996") 
     } 
     typeRs { 
      eq("classCode", "WD996") 
     } 
    } 
} 

我需要爲這一說法做一個查詢的內容:「獲取所有IonicBond其中或者其TypeII孩子中的一個或TypeR兒童classCode等於‘WD996’」。問題是,只有在IonicBond實例同時具有TypeIITypeR子項時,此查詢纔會起作用。這將不包括:

  1. IonicBondTypeR孩子「WD996」的class價值,但沒有TypeII孩子。
  2. IonicBondTypeII孩子class值「WD996」但沒有TypeR孩子。

我該如何將它包含到結果集中?

+0

在'typeIIs'閉包中加入'isNull('typeRs')',在'typeRs'閉包中加入'isNull('typeIIs')''應該這樣做吧? – dmahapatro

回答

0

我發現createCriteria()使用INNER JOIN默認情況下,這意味着它會真的不包括IonicBond情況下只具有typeIIs孩子,或typeRs,只有兩個。解決的辦法是將其更改爲使用createAlias()一個LEFT JOIN

import org.hibernate.Criteria 

... 
    ArrayList<IonicBond> list = IonicBond.createCriteria().list { 
     createAlias('typeIIs', 'typeIIs', Criteria.LEFT_JOIN) 
     createAlias('typeRs', 'typeRs', Criteria.LEFT_JOIN) 

     or { 
      eq("typeIIs.classCode", "WD996") 
      eq("typeRs.classCode", "WD996") 
     } 
    } 

注意Hibernate不會使用LEFT JOIN默認加入,即使你所有的孩子都設置爲constraints.nullable: true。您必須手動聲明它。

1

嘗試這種解決方案:

ArrayList<IonicBond> list = IonicBond.where { typeRs { classCode == "WD996" } || typeIIs { classCode == "WD996" } }.list() 
0

獨立標準是查詢GORM的一種方式。首先使用要執行查詢的域類的名稱創建DetachedCriteria。然後你用'where'查詢或標準查詢調用方法'build'。

def criteria = new DetachedCriteria(IonicBond).build { 

    or { 
      typeIIs { 
       eq("classCode", "WD996") 
      } 
      typeRs { 
       eq("classCode", "WD996") 
      } 
     } 

} 
def result = criteria.list() 
+1

請詳細說明此代碼如何回答問題。 – JAL

+0

是的,'build'關閉了什麼? – Gideon