Проекции критериев Grails - получают количество строк

У меня есть объект Отеля:

class Hotel {
City city
}

Теперь, мне нужно количество отелей с данным городом. Это могло быть сделано таким образом:

def hotels = Hotel.findAllByCity(city)
def cnt = hotels.size()

Но это - очень грязный путь. Кажется, что с критериями это было бы лучше, но я понятия не имею, как реализовать его...

17
задан Oleksandr 24 February 2010 в 16:46
поделиться

2 ответа

Есть динамические счетчики, а также средства поиска по объектам домена:

Hotel.countByCity(city)

Более подробная информация в руководстве пользователя , конечно же

23
ответ дан 30 November 2019 в 10:07
поделиться

Дэйв прав в том, что вы можете использовать методы countBy * для простого подсчета. Если вам нужно более двух критериев, вам придется вернуться к api критериев , HQL или SQL. Очень часто требуется более двух критериев, особенно при активной и развивающейся кодовой базе.

Вот пример того, как вы могли бы использовать Criteria api для прогнозов :

def c = Hotel.createCriteria()

def hotelCount = c.get {
    projections {
        count('id')
    }
    gt("stars", 2)          
    eq("city", city)            
    eq("deleted", false)

}

В качестве альтернативы (более элегантно) вы даже можете использовать Criteria # count следующим образом:

def c = Hotel.createCriteria()

def hotelCount = c.count {
    gt("stars", 2)          
    eq("city", city)            
    eq("deleted", false)

}

Для полноты:

class Hotel {
    City city
    Boolean deleted = false
    Integer stars
}

class City {
    String name
}

Интеграционный тест (с использованием подключаемого модуля build-test-data )

import grails.test.*

class HotelTests extends GrailsUnitTestCase {

    void testCriteria() {
        City city1 = City.build(name:'one')
        assertNotNull(city1)
        City city2 = City.build(name:'two')
        assertNotNull(city1)

        Hotel fiveStarHotel= Hotel.build(city:city1, deleted:false, stars:5)
        assertNotNull(fiveStarHotel)

        Hotel hotelInCity2 = Hotel.build(city:city2, deleted:false, stars:5)
        assertNotNull(hotelInCity2)

        Hotel deletedHotel = Hotel.build(city:city1, deleted:true, stars:5)
        assertNotNull(deletedHotel)

        Hotel threeStarHotel = Hotel.build(city:city1, deleted:false, stars:3)
        assertNotNull(threeStarHotel)

        Hotel oneStarHotel = Hotel.build(city:city1, deleted:false, stars:1)
        assertNotNull(oneStarHotel)

        def c = Hotel.createCriteria()

        def hotelCount = c.get {
            projections {
                count('id')
            }
            gt("stars", 2)          
            eq("city", city1)           
            eq("deleted", false)

        }
        assertEquals(2, hotelCount) //should only find the 5 and 3 star hotel

        def c2 = Hotel.createCriteria()
        hotelCount = c2.count {
            gt("stars", 2)          
            eq("city", city1)           
            eq("deleted", false)

        }
        assertEquals(2, hotelCount) //should only find the 5 and 3 star hotel
    }
}
47
ответ дан 30 November 2019 в 10:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: