Search code examples
hibernategrailsgrails-orm

Eager fetching the entire object tree in grails


So I have an few objects in the domain which are in a hasMany relation with each other as below

Class Car {
    String name
    SortedSet tires = [] as SortedSet
    static hasMany = [tires: Tire]
}

Class Tire {
    String type
    SortedSet screws = [] as SortedSet
    static hasMany = [screws: Screw]
}

Class Screws {
     String type
}

Now I would like to take the entire object tree offline for a certain kind of car that I can get by a findByName. I know we can do a fetch eager on the finder, but that goes down just one level. As in the example I have 2 levels or more.

So my question is this. Is there an elegant solution to eager fetch the entire object tree and then use it around without grails/Hibernate firing off another query to fetch the details.

I tried the following which seem to have a similar result but are hardly elegant.

The withCriteria solution

def cars = Car.withCriteria {
    tires {
        screws {
            join 'screws'
        }
    }

Also I tried converting the entire tree into JSON and reparsing it, but that seems to be an overkill. I guess basically I am trying to get the whole object tree offline. Any thoughts if this can be done easily or at all?

TIA


Solution

  • Using the mapping closure:

    Class Car {
        String name
        SortedSet tires = [] as SortedSet
        static hasMany = [tires: Tire]
        static mapping = {
            tires lazy: false
        }
    }
    
    Class Tire {
        String type
        SortedSet screws = [] as SortedSet
        static hasMany = [screws: Screw]
        static mapping = {
            screws lazy: false
        }
    }
    
    Class Screws {
         String type
    }
    

    Maybe you should to take the exception like the rule, I mean, you can to configure your domains class to be lazy: false and to call your finder with fetch lazy:

    def cars = Car.findAllByType(type: "Alfa", [fetch: [tires: 'lazy']])
    

    I don't know if that is a valid option but you can try it.