2010-02-24 13 views
15

Ich habe Hotels Einheit:Grails Kriterien Projektionen - get Reihen zählen

class Hotel { 
City city 
} 

Nun, ich brauche Anzahl der Hotels mit bestimmten Stadt. Es könnte auf diese Weise geschehen:

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

Aber es ist sehr schmutzig Art und Weise. Es scheint, dass mit Kriterien würde es besser sein, aber ich habe keine Ahnung, wie es zu implementieren ...

Antwort

23

Es gibt dynamische Zähler sowie Finders auf Domain-Objekten:

Hotel.countByCity(city) 

Weitere Details in den user guide natürlich

44

Dave is right dass Sie die countBy* Methoden für einfaches Zählen verwenden können. Wenn Sie mehr als zwei Kriterien benötigen, müssen Sie zu criteria api, HQL oder SQL zurückkehren. Es ist sehr üblich, mehr als zwei Kriterien zu benötigen, insbesondere bei einer aktiven und sich entwickelnden Codebasis. Hier

ist ein Beispiel dafür, wie Sie die Criteria api tun projections verwenden würde:

def c = Hotel.createCriteria() 

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

} 

Alternativ (eleganter) Sie könnten auch Kriterien verwenden # zählen wie folgt aus:

def c = Hotel.createCriteria() 

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

} 

Nur aus Gründen der Vollständigkeit:

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

class City { 
    String name 
} 

Ein integr (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 
    } 
} 
+0

nur für die Einfachheit, wie kann ich die Kriterien in einer Zeile setzen? sollte ich Semikolon (;) für jede Anweisung hinzufügen? –

+0

Ich glaube, du kannst: Hotel.createCriteria(). Count {gt ("stars", 2); eq ("Stadt", Stadt); eq ("deleted", false)} aber ich habe es noch nicht ausprobiert. –

+0

getestet und getestet ... es funktioniert! Vielen Dank! –

Verwandte Themen