Search code examples
hibernategrailsgrails-orm

Criteria query on a property of a one-to-many property in GORM


I have a one-to-many relationship between the following example classes:

Class Home {
    static hasMany = [loans: Loan]

    int numStories
}

Class Loan {
    static belongsTo = [Bank]

    Home  home
    int   yearIssued 
}

Class Bank {
    SortedSet loans
    static  hasMany   = [loans: Loan]

    boolean active
}

I'm trying to write a named query that gets all active Bank objects that have Loans issued in 2007 on Homes of 2 stories. In the Bank namedQueries I tried:

static namedQueries = { 
    myNamedQuery { yearIssued, numStories ->

        eq 'active', true
        loans {
            gt 'yearIssued', yearIssued

            home {
                eq 'numStories', numStories
            }
        }
    }
}

If I remove the "home { eq ... }" portion above, the query works fine, it just doesn't limit to 2 stories. When executed as above, I get a groovy.lang.MissingMethodException error like:

   No signature of method: package.stuff.Home.call() is applicable for argument types
(package.stuff.Bank$__clinit__closure3_closure10_closure20_closure21) 
values: [package.stuff.Bank$__clinit__closure3_closure10_closure20_closure21@746231ed];

    Possible solutions: wait(), last(), save(), any(), getAll(), wait(long)" 

How would I limit the Banks returned to those that have loans on homes with 2 stories?


Solution

  • Well, after many attempts I was never able to get it working using the direct association dsl with more than one level of association. I was able to get it to work using aliases:

     static namedQueries = { 
       myNamedQuery { yearIssued, numStories ->
         eq 'active', true
         createAlias 'loans','l'
         createAlias 'l.home','h'
         gt('l.yearIssued', yearIssued)
         eq('h.numStories',numStories)
      }
    }
    

    An then call it using

    def bankInstanceList = Bank.myNamedQuery(2007,2).list()
    

    I'm not sure at the moment why this is - could be a bug or just designed behavior I don't understand.

    Hopefully this at least gets you going...