Grails 标准预测 - 获取行数

Posted

技术标签:

【中文标题】Grails 标准预测 - 获取行数【英文标题】:Grails criteria projections - get rows count 【发布时间】:2011-01-20 15:04:57 【问题描述】:

我有酒店实体:

class Hotel 
City city

现在,我需要指定城市的酒店数量。 可以这样实现:

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

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

【问题讨论】:

【参考方案1】:

Dave is right,您可以使用countBy* 方法进行简单计数。如果您需要两个以上的条件,则必须恢复为 criteria api、HQL 或 SQL。需要两个以上的标准是很常见的,尤其是对于一个活跃且不断发展的代码库。

这是一个示例,说明如何使用Criteria api 执行projections:

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 plugin)

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
    

【讨论】:

为简单起见,如何将标准放在一行中?我应该为每条语句添加分号 (;) 吗? 相信你可以做到:Hotel.createCriteria().count gt("stars", 2); eq("城市", 城市); eq("deleted", false) 但我还没试过。 如果我想知道哪些城市有不止一家酒店? 看起来 GORM 条件查询中不支持“have”子句,但在 HQL 中。【参考方案2】:

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

Hotel.countByCity(city)

更多详情当然在user guide 中

【讨论】:

以上是关于Grails 标准预测 - 获取行数的主要内容,如果未能解决你的问题,请参考以下文章

Grails/GORM“入”标准

Grails:将堆栈跟踪记录到标准输出

下面的 SQL 的 GORM(grails) 标准是啥?

Grails:标准构建器中的字段总和

重用 Grails 标准闭包的一部分

Grails 控制器变量在视图中不可见