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
static belongsTo = [airport:Airport]
}
Given the above domain classes and the following code:
def airport = Airport.findByName("Gatwick")
airport.flights.each {
println it.name
}
GORM will execute a single SQL query to fetch the
Airport
instance and then 1 extra query
for each iteration over the
flights
association. In other words you get N+1 queries.
This can sometimes be optimal depending on the frequency of use of the association as you may have logic that dictates the associations is only accessed on certain occasions.
Configuring Eager Fetching
An alternative is to use eager fetching which can specified as follows:
class Airport {
String name
static hasMany = [flights:Flight]
static mapping = {
flight fetch:"join"
}
}
In this case the association will be
Airport
instance and the
flights
association will be loaded all at once (depending on the mapping). This has the benefit of requiring fewer queries, however should be used carefully as you could load your entire database into memory with too many eager associations.
Associations can also be declared non-lazy using 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. Essentially, you can configure Hibernate to lazily fetch results in "batches". For example:
class Airport {
String name
static hasMany = [flights:Flight]
static mapping = {
flight 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
}
}