ShatyUT
ShatyUT

Reputation: 1365

Grails: querying hasMany association

I know there are several questions on this subject but none of them seem to work for me. I have a Grails app with the following Domain objects:

class Tag {
    String name
}

class SystemTag extends Tag {
    // Will have additional properties here...just placeholder for now
}

class Location {
    String name
    Set<Tag> tags = []
    static hasMany = [tags: Tag]
}

I am trying to query for all Location objects that have been tagged by 1 or more tags:

class LocationQueryTests {

    @Test
    public void testTagsQuery() {
        def tag = new SystemTag(name: "My Locations").save(failOnError: true)
        def locationNames = ["L1","L2","L3","L4","L5"]
        def locations = []
        locationNames.each {
            locations << new Location(name: it).save(failOnError: true)
        }
        (2..4).each {
            locations[it].tags << tag
            locations[it].save(failOnError: true)
        }

        def results = Location.withCriteria {
            tags {
                'in'('name', [tag.name])
            }
        }

        assertEquals(3, results.size())     // Returning 0 results
    }
}

I have validated that the data is being created/setup correctly...5 Location objects created and the last 3 of them are tagged.

I don't see what's wrong with the above query. I would really like to stay away from HQL and I believe that should be possible here.

Upvotes: 0

Views: 991

Answers (2)

Arturo Herrero
Arturo Herrero

Reputation: 13140

You should use addTo* for adds a domain class relationship for one-to-many or many-to-many relationship.

(2..4).each {
    locations[it].addToTags(tag)
}

Upvotes: 1

nate_weldon
nate_weldon

Reputation: 2349

Welcome to hibernate.

The save method informs the persistence context that an instance should be saved or updated. The object will not be persisted immediately unless the flush argument is used

if you do not use flush it does the saves in batches so when you setup your query right after the save it appears that the data is not there.

you need to add

 locations[it].save(failOnError: true, flush:true)

Upvotes: 1

Related Questions