Grails标准投影 - 获取行数

Ole*_*ndr 17 java grails hibernate

我有酒店实体:

class Hotel {
City city
}
Run Code Online (Sandbox Code Playgroud)

现在,我需要有特定城市的酒店数量.它可以这样做:

def hotels = Hotel.findAllByCity(city)
def cnt = hotels.size()
Run Code Online (Sandbox Code Playgroud)

但这是非常肮脏的方式.似乎有了标准会更好,但我不知道如何实现它......

Col*_*ton 47

Dave是对的,您可以使用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)

}
Run Code Online (Sandbox Code Playgroud)

或者(更优雅地)你甚至可以像下面这样使用Criteria#计数:

def c = Hotel.createCriteria()

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

}
Run Code Online (Sandbox Code Playgroud)

为了完整起见:

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

class City {
    String name
}
Run Code Online (Sandbox Code Playgroud)

集成测试(使用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
    }
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*wer 23

域对象上有动态计数器和查找程序:

Hotel.countByCity(city)
Run Code Online (Sandbox Code Playgroud)

当然,用户指南中有更多细节