czwartek, 25 lipca 2013

Grails one to many: Find object by property of one of child-object from collection

Leave a Comment
Have you ever looking for solution of a problem that became obvious in the moment that you find it. In my case I have tried to find Grails domain object by property of one of its child  Assume that there are persons and pets. Each person can have one or more pets. Each pet has one owner.

class Person {
    
    String name
    
    static hasMany = [pets: Pet]
}

class Pet {

    String name
    int age

    static belongsTo = [person: Person]
}

Lets find all persons that have at least one pet with name "reksio". This is really simple challenge. That  how it looks with using namedQueries

class Person {
    
    String name
    
    static hasMany = [pets: Pet]
    
    static namedQueries = {
        findByPetName { String petName ->
            pets {
                eq "name", petName
            }
        }
    }
}
Thus it is time to check if  the solution really works. I have prepared some integration test using Spock.

class PersonIntegrationSpec extends IntegrationSpec {

    def  'find all persons with pet with given name'() {
        given:
            Pet reksio1 = new Pet(name: "reksio", age: 2)
            Pet rocky1 = new Pet(name: "rocky", age: 4)
            Pet max = new Pet(name: "max", age: 7)
            Person person1 = new Person(name: "Jack")
            [reksio1, rocky1, max].each { person1.addToPets(it) }
            person1.save(failOnError: true)

            Pet teddy = new Pet(name: "teddy", age: 2)
            Pet reksio2 = new Pet(name: "reksio", age: 12)
            Pet gizmo = new Pet(name: "gizmo", age: 11)
            Person person2 = new Person(name: "Kate")
            [teddy, reksio2, gizmo].each { person2.addToPets(it) }
            person2.save(failOnError: true)

            Pet rocky2 = new Pet(name: "rocky", age: 2)
            Pet bandit = new Pet(name: "bandit", age: 12)
            Person person3 = new Person(name: "John")
            [rocky2, bandit].each { person3.addToPets(it) }
            person3.save(failOnError: true)

        when:
            List persons =  Person.findByPetName("reksio").list()

        then:
            persons.size() == 2
            persons.contains(person1)
            persons.contains(person2)        
    }
}

This is really simple, clear and obvious.

0 komentarze:

Prześlij komentarz