I have two models with a hasMany relation
class Puturru implements Serializable {
String name
Set<Fua> fuas
static hasMany = [fuas: Fua]
static constraints = {
fuas(nullable: true)
}
}
And
class Fua {
String name
static constraints = {
}
}
When running the next test I'm getting a LazyInitializationException
void "test something"() {
given:
def puturrus
Puturru.withNewSession { session ->
p = Puturru.build()
Fua f
for (int i = 0; i < 10; i++) {
f = Fua.build()
p.addToFuas(f)
}
f.save(failOnError: true, flush: true)
}
when:
Puturru.withNewSession {
puturrus = Puturru.createCriteria().listDistinct {
fetchMode("fuas", FetchMode.JOIN)
}
}
then:
Puturru.withNewSession {
assert puturrus.fuas*.name.size() > 0
}
p.fuas.each { it.delete() }
p.delete()
}
If I set puturrus mapping
static mapping = {
fuas lazy: false
}
Then all the elements are retrieved although it uses multiple selects, otherwise it use this query
select ...
from puturru ...
left outer join puturru_fua fuas2_ on this_.id=fuas2_.puturru_fuas_id
I can't set mapping in the real app, because I don't want to fetch all entries in all cases. To me looks like I'm missing something to make the criteria go further than the intermediate table.
I'm using grails 2.3.6 and hibernate 3.6.10.8.
Do somebody know why is not getting the "fuas" objects?
I have been trying to do some changes to the domains and test aiming to figure out what the problem is.
After @sudhir suggestion, I started playing with joins I changed the criteria to something like
puturrus = Puturru.createCriteria().listDistinct {
fuas {
}
}
Then the query generated by gorm and hibernate was
select ...
from puturru this_
inner join puturru_fua fuas3_ on this_.id=fuas3_.puturru_fuas_id
inner join fua fuas_alias1_ on fuas3_.fua_id=fuas_alias1_.id
This time we got all the entries but not their relations with the puturrus domains. We compromise and put a second query just for getting the associations, so for the time being the second session block is
Puturru.withNewSession {
puturrus = Puturru.createCriteria().listDistinct {
fuas {
}
}
Puturru.createCriteria().listDistinct {
fetchMode("fuas", FetchMode.JOIN)
}
}
This is way better than my previous approach that was iterate over all the puturrus and all the fuas within the criteria session, but I think is still sub-optimal, so are there any way to get both the data and the associations in a single query?
We found a proper solution using createAlias
Puturru.withNewSession {
puturrus = Puturru.createCriteria().listDistinct {
createAlias("fuas", "fuas", CriteriaSpecification.LEFT_JOIN)
}
}
Actually it seems to be a bug in Hibernate 3.6 already fixed in Hibernate 4