在Grails子查询中使用Disjunction(逻辑或)

时间:2016-10-25 18:12:03

标签: grails gorm

在Grails 2.5.4中,我遇到了在子查询中使用析取的问题。如果我有如下查询:

DomainObj.createCriteria().list {
   def criteria = new DetachedCriteria(DomainObj2).build {
       or {
           eq('prop1', someVal)
           eq('prop2', someVal)
           eq('prop3', someVal)
       }
       projections {
           distinct('id')
       }
   }
   inList('prop', criteria)
}

查询的“或”部分失败,并出现空指针异常。原因似乎是在AbstractHibernateCriterionAdapter中,代码正在寻找从未分配的DetachedCriteria的PersistentEntity。

我找到的唯一解决方法是切换查询以使用更多子查询,如下所示:

   def criteria1 = new DetachedCriteria(DomainObj2).build {
           eq('prop1', someVal)
       projections {
           distinct('id')
       }
   }
   def criteria2 = new DetachedCriteria(DomainObj2).build {
           eq('prop2', someVal)
       projections {
           distinct('id')
       }
   }
   def criteria3 = new DetachedCriteria(DomainObj2).build {
           eq('prop3', someVal)
       projections {
           distinct('id')
       }
   }
   DomainObj.createCriteria().list {
       or {
           inList('prop', criteria1)
           inList('prop', criteria2)
           inList('prop', criteria3)
       }
   }

哪个回避这个问题,真的不太理想。知道出了什么问题吗?

更新

所以在浏览了一些之后,我在Github上找到了this issue。我所遇到的是一个在grails-data-mapping版本5.0.2中修复的错误。因此,对于将来搜索此问题的任何人来说,您可能需要升级或使用上面突出显示的疯狂解决方法。

1 个答案:

答案 0 :(得分:1)

你可以将上面的工作巢简化为:

 private DetachedCriteria getCriteria(prop,val) {
      return new DetachedCriteria(DomainObj2).build {
           eq(prop,val)
       projections {
           distinct('id')
       }
   }
   DomainObj.createCriteria().list {
       or {
           inList('prop', getCriteria('prop1','somVal'))
           inList('prop', getCriteria('prop2','somVal'))
           inList('prop',  getCriteria('prop3','somVal'))
       }
   }

我个人可能只是do a findAll或者只是运行一个hql查询,如果事实证明由于某些限制你不能使用当前的方法,因为我自己并不是这方面的专家。

//where d.domainObject2 is the binding of DomainObj2 within DomainObj
    String query="select new map(d.id) from DomainObj d left join d.domainObject2 d2 where d2.field in (:someList)" 
def input=[]
input.someList=[1,2,3]   //The or segments
    def results=DomainObj.executeQuery(query,[],[readOnly:true,timeout:15,max:-1])