Reputation: 638
I'm trying to build a hierarchy of a class I've called group. The domain is fairly simple:
class SubGroup implements Serializable {
Group child
Group parent
static mapping = {
id composite: ['child', 'parent']
}
}
class Group implements Serializable {
int groupId
String key
String title
static mapping = {
id name: 'groupId'
}
}
Basically I'd like to build up a map of group parents and their associated children. So I'm looping through each record (if there's a cleaner way to query for a Map I'm happy to hear it) and creating the map entry for it.
Map hierarchy = [:]
SubGroup.list().each { relation ->
if (!hierarchy[relation.parent]) {
hierarchy[relation.parent] = new HashSet()
}
hierarchy[relation.parent] << relation.child
}
I would think hibernate would use some simple query that does this something like this:
select * from sub_group s, group c, group p
where s.child_id = c.group_id and s.parent_id = p.group_id
But it is not doing the join. It is doing a query of the subgroup followed by n queries of the group table (N+1 select problem). Ugh. I heard in 2.0 there's a problem with the hibernate query cache so I disabled it. I've tried adding lazy: false, and fetch: join to my SubGroup domain class for both the parent and the child columns with no luck. I've tried adding (fetch: [child: 'eager']) as a parameter to the list method. It will not do the join. Am I missing something? To be honest, it shouldn't really even need to do a join as I am only accessing the groupId foreign key property although later on I will need both the key and title properties.
I could, of course, make the child and parent properties ints and just do my own querying when I need the rest of the data or I could use HQL and some other method for limiting this to a single query, but it seems like GORM should be doing this for me. Thanks for your help.
Regards,
Jim
Upvotes: 0
Views: 267
Reputation: 638
It seems the only way I could get this to work without hibernate making a select call for each child and parent was to instead do a HQL query rather than using the list method as shown below:
Map hierarchy = [:]
def subGroups = SubGroup.executeQuery("SELECT s.parent, s.child FROM SubGroup s")
subGroups.each { relation ->
if (!hierarchy[relation[0]]) {
hierarchy[relation[0]] = new HashSet()
}
hierarchy[relation[0]] << relation[1]
}
Thus I'm really only using the SubGroup domain class to define the relationships. I would think I should be able to do this via some kind of mapping but I couldn't figure out how.
Upvotes: 0