7.3.4 Eager and Lazy Fetching 3.1.4

See the light - agile, industrial strength, rapid web application development made easy

(Quick Reference) # 7.3.4 Eager and Lazy Fetching - Reference Documentation Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari Version: 3.1.4 ## 7.3.4 Eager and Lazy Fetching Associations in GORM are by default lazy. This is best explained by example:
    class Airport {
        String name
        static hasMany = [flights: Flight]
    }
    class Flight {
        String number
        Location destination
        static belongsTo = [airport: Airport]
    }
    class Location {
        String city
        String country
    }
Given the above domain classes and the following code:
    def airport = Airport.findByName("Gatwick")
    for (flight in airport.flights) {
        println flight.destination.city
    }
GORM will execute a single SQL query to fetch the `Airport` instance, another to get its flights, and then 1 extra query for each iteration over the `flights` association to get the current flight's destination. In other words you get N+1 queries (if you exclude the original one to get the airport). ### Configuring Eager Fetching An alternative approach that avoids the N+1 queries is to use eager fetching, which can be specified as follows:
    class Airport {
        String name
        static hasMany = [flights: Flight]
        static mapping = {
            flights lazy: false
        }
    }
In this case the `flights` association will be loaded at the same time as its `Airport` instance, although a second query will be executed to fetch the collection. You can also use `fetch: 'join'` instead of `lazy: false` , in which case GORM will only execute a single query to get the airports and their flights. This works well for single-ended associations, but you need to be careful with one-to-manys. Queries will work as you'd expect right up to the moment you add a limit to the number of results you want. At that point, you will likely end up with fewer results than you were expecting. The reason for this is quite technical but ultimately the problem arises from GORM using a left outer join. So, the recommendation is currently to use `fetch: 'join'` for single-ended associations and `lazy: false` for one-to-manys. Be careful how and where you use eager loading because you could load your entire database into memory with too many eager associations. You can find more information on the mapping options in the section on the ORM DSL. ### Using Batch Fetching Although eager fetching is appropriate for some cases, it is not always desirable. If you made everything eager you could quite possibly load your entire database into memory resulting in performance and memory problems. An alternative to eager fetching is to use batch fetching. You can configure Hibernate to lazily fetch results in "batches". For example:
    class Airport {
        String name
        static hasMany = [flights: Flight]
        static mapping = {
            flights batchSize: 10
        }
    }
In this case, due to the `batchSize` argument, when you iterate over the `flights` association, Hibernate will fetch results in batches of 10. For example if you had an `Airport` that had 30 flights, if you didn't configure batch fetching you would get 1 query to fetch the `Airport` and then `30` queries to fetch each flight. With batch fetching you get 1 query to fetch the `Airport` and 3 queries to fetch each `Flight` in batches of 10. In other words, batch fetching is an optimization of the lazy fetching strategy. Batch fetching can also be configured at the class level as follows:
    class Flight {
        …
        static mapping = {
            batchSize 10
        }
    }
Check out part 3 of the GORM Gotchas series for more in-depth coverage of this tricky topic. | Quick Reference (hide)