简体   繁体   中英

Grails: “where” query with optional associations

I'm trying to run a "where" query to find a domain model object that has no association with another domain model object or if it does, that domain model object has a specific property value. Here's my code:

query = Model.where({
  other == null || other.something == value
})
def list = query.list()

However, the resulting list only contains objects that match the second part of the OR statement. It contains no results that match the "other == null" part. My guess is that since it's checking a value in the associated object its forcing it to only check entries that actually have this associated object. If that is the case, how do I go about creating this query and actually having it work correctly?

You have to use a LEFT JOIN in order to look for null associations. By default Grails uses inner join which will not be joined for null results. Using withCriteria as below you should get the expected results:

import org.hibernate.criterion.CriteriaSpecification

def results = Model.withCriteria {
    other(CriteriaSpecification.LEFT_JOIN){
        or{
            isNull 'id'
            eq 'something', value
        }
    }
}

UPDATE
I know aliasing is not possible in DetachedCritieria where one would try to specify the join as in createCriteria/withCriteria . There is an existing defect regarding adding the functionality to DetachedCriteria . Just adding the work around for where query as mentioned in defect.

Model.where {
    other {
        id == null || something == value
    }
}.withPopulatedQuery(null, null){ query -> 
    query.@criteria.subcriteriaList[0].joinType = CriteriaSpecification.LEFT_JOIN
    query.list()
}

I would rather use withCriteria instead of the above hack .

this might work:

query = Model.where({
  isNull( other ) || other.something == value
})

If that wouldn't work, try something like:

  other.id == null || other.something == value

UPDATE:

or with good'ol criteria query:

list = Pack.withCriteria{
  or{
    isNull 'other'
    other{ eq 'something', value }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM