Grails criteria projections - get rows count

前端 未结 2 1023
轮回少年
轮回少年 2021-02-12 17:49

I have Hotel entity:

class Hotel {
City city
}

Now, i need count of hotels with given city. It could be done in this way:

def h         


        
2条回答
  •  抹茶落季
    2021-02-12 18:14

    Dave is right that you can use the countBy* methods for simple counting. If you need more than two criteria you will have to revert to the criteria api, HQL or SQL. It is very common to need more than two criteria especially with an active and evolving codebase.

    Here is an example of how you would use the Criteria api to do projections:

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

    Alternatively (more elegantly) you could even use Criteria#count like the following:

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

    Just for completeness sake:

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

    An integration test (using the 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
        }
    }
    

提交回复
热议问题