Grails 2.x createCriteria 'или' не работает для вложенных ассоциаций

Кажется, что в Grails 2.x, если у вас есть ассоциация класса домена, и вы пытаетесь запустить createCriteria, используя or для этого отношения + другой запрос, or проигнорирует другой запрос и просто использует результаты вложенной ассоциации. Я понимаю, что это может быть немного запутанным, поэтому вот пример:

class Passenger {
    Long id
    Boolean isDriving
}

class Car {
    Long id
    Passenger passenger
    Boolean isMoving

    static constraints = {
        passenger nullable: true
    }
}

и тест:

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
    }
}

Этот же код работал в более старых версиях Grails, но, похоже, не работает сейчас — кто-нибудь знает хороший обходной путь, кроме выполнения нескольких запросов?


person Igor    schedule 15.10.2013    source источник
comment
Попробуйте включить ведение журнала гибернации и посмотреть, какой sql генерируется. В качестве обходного пути вы можете просто написать hql-запрос, но вам не нужно   -  person Jim Sosa    schedule 16.10.2013
comment
@JimSosa Да, я попробую с ведением журнала. Я надеялся не использовать HQL, но да, возможно, мне придется.   -  person Igor    schedule 16.10.2013


Ответы (1)


ОБНОВЛЕНИЕ:
После выпуска Grails 2.x Criteria по умолчанию использует соединение inner, но в этом конкретном случае необходимо использовать соединение outer, поскольку ассоциация пассажиров не позволит следовать условию or, если это inner присоединиться, а пассажир не настроен на машину.

import org.hibernate.Criteria

def queryResults = Car.createCriteria().list() {
    createAlias('passenger', 'passenger', Criteria.LEFT_JOIN)
    or {
        eq('isMoving', true)
        eq('passenger.isDriving', true)
    }
}
person dmahapatro    schedule 15.10.2013
comment
@GrailsGuy Смотрите мое обновление. Необходимо использовать внешнее соединение. - person dmahapatro; 16.10.2013
comment
Обратите внимание, что в grails 3/hibernate 4+ Criteria устарела и вместо этого должна быть JoinType.LEFT_OUTER_JOIN, но в остальном все еще идеальный ответ. - person Trebla; 14.09.2017