Reputation: 216
In Grails 2.5.4, I am having issues using a disjunction in Subqueries. If I have a query like the following:
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)
}
The 'or' part of the query fails with a null pointer exception. The reason seems to be in AbstractHibernateCriterionAdapter the code is looking for a PersistentEntity for the DetachedCriteria which is never assigned.
The only workaround I have found is to switch the query to use more subqueries like this:
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)
}
}
Which sidesteps the issue, and really isn't ideal. Any idea what is going wrong?
Update
So after looking around some more I found this issue on Github. What I am experiencing is a bug that was fixed in grails-data-mapping version 5.0.2. So for anyone that searches for this issue in the future it looks like the you either have to upgrade or use the crazy workaround highlighted above.
Upvotes: 1
Views: 216
Reputation: 8587
You could probably simplify your above working nest to:
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'))
}
}
Personally I would probably either just do a findAll or just run an hql query, if it turns out you can't use the current method due to some limitation since am no expert on this matter itself.
//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])
Upvotes: 1