Grails criteria query returns multiple copies of same object when eagerly loaded

140 Views Asked by At

This seems like a basic question so I assume I'm just doing something really boneheaded. I'm trying to navigate a large structure of objects and would like them to be eagerly loaded in a particular query:

class Box {
  String name
  hasMany = [marbles:Marble]

  static mapping = {
    sort 'name'
  }
}

and

class Marble {
  String name
  static belongsTo = Box
}

So if I do:

List boxes = Box.withCriteria() {
  eq("id", 0)
}
log.info("Boxes returned: ${boxes.size()")

I see there is one box returned as expected, if I try to eagerly load the marbles, however...

List boxes = Box.withCriteria() {
  eq("id", 0)
  marbles {}
}
log.info("Boxes returned: ${boxes.size()")

There are 129 boxes returned (or more accurately, 129 copies of the same box, which is correct for "number of marbles in this box"). There are additionally two more tiers of 1:M relationships I'd like to eagerly load here... what do I need to do to eagerly load the associations and still only receive one Box as a result?

Edit: Per my comment below, the following appears to work. I'd be happy to continue to pursue other options, but in the meantime, the "best" solution appears to be:

def c = Box.createCriteria()
c.listDistinct {
  eq("id", 0)
  marbles {}
}
1

There are 1 best solutions below

2
On

Try specifying eager loading in your mapping:

class Box {
  String name
  hasMany = [marbles:Marble]

  static mapping = {
    sort 'name'
  }
static fetchMode = [marbles: "eager"]

}

Then just get the box - if you add marbles to the criteria as you did in your second example then you are joining box and marbles and you will get the same number of rows as there are marbles as expected.

List boxes = Box.withCriteria() {
  eq("id", 0)
}