Grails 2.x createCriteria 'or' doesn't

2019-02-10 16:21发布

问题:

It seems that in Grails 2.x, if you have a domain class association, and you try to run a createCriteria using or on that relation + another query, the or will ignore the other query and just use the results of the nested association. I realize this may be a little confusing, so here is an example:

class Passenger {
    Long id
    Boolean isDriving
}

class Car {
    Long id
    Passenger passenger
    Boolean isMoving

    static constraints = {
        passenger nullable: true
    }
}

and a test:

class CarIntegrationTests {
    @Test
    void testCar() {
    Passenger passenger1 = new Passenger(isDriving: true)
    passenger1.save()

    Car car1 = new Car(passenger: passenger1, isMoving: false)
    Car car2 = new Car(isMoving: true)

    car1.save()
    car2.save()

        def queryResults = Car.createCriteria().list() {
            or {
                eq('isMoving', true)// This by itself works

                passenger {// And this by itself works
                    eq('isDriving', true)
                }
            }// But OR'd, it only returns the results of the nested part
        }

        assertEquals 2, queryResults.size() // Returns 1
    }
}

This same code worked in older versions of Grails, but doesn't not seem to work now -- does anyone know of a good workaround to this, other than running multiple queries?

回答1:

UPDATE:
Post Grails 2.x, Criteria by default uses inner join, but for this particular case outer join has to be used as passenger association will not allow to follow or condition if it is an inner join and passenger is not set to car.

import org.hibernate.Criteria

def queryResults = Car.createCriteria().list() {
    createAlias('passenger', 'passenger', Criteria.LEFT_JOIN)
    or {
        eq('isMoving', true)
        eq('passenger.isDriving', true)
    }
}