Grails GORM loading collection of objects issue
I'm trying to load a list of Evaluations in a class named Contributor but I'm missing something as I cannot get my test passing.
My test is creating and saving objects as expected because when I do Evaluations.list() and Contributor.list() and print the values I see the data I saved.
Furthermore, when I select an Evaluation and print the value of its 'contributor' property it appears to be correct.
However, when I select a Contributor and print the values of its 'evaluations' property it is null.
I assume my mapping is the problem?
class Contributor {
String name
static hasMany = [evals:Evaluation]
static mapping = {
id column: 'user_id'
evals joinTable:[name:'ev开发者_如何学编程aluation', column:'eval_id', key:'eval_user_id']
version false
}
}
class Evaluation {
Contributor contributor
String comment
static mapping = {
id column:'eval_id'
contributor column:'eval_user_id'
version false
}
}
Thanks.
You shouldn't assign evals
like contributor.evals = [eval]
. Rather invoke a dynamic method addTo*()
: contributor.addToEvals(eval)
. This will create a Hibernate collection for evals
which will be persisted later.
The first one didn't work because Grails doesn't assign other end of association when you assign eval.contributor
, i.e. it doesn't call contributor.addToEvals(eval)
. I have no idea why - there must be some implementation reason.
So contributor
remains with the same empty evals
in Hibernate cache. If it falls out of cache and you re-read it, it will have evals
filled, because the association is mapped only on Eval
table's foreign key.
Empty evals
are null - it's another Hibernate feature: when a collection is empty, it can be null. Just know it.
Here's an good short post explaining some Hibernate internals: http://blog.xebia.com/2008/03/advanced-hibernate-proxy-pitfalls/
Ahh I've sussed it. The problem is the way I was saving the objects.
The following does not work:
def contributor = new Contributor([name:'Homer']).save(failOnError:true)
def eval = new Evaluation([contributor:contributor, comment:'Must read article']).save(failOnError:true)
This
def contributor = new Contributor([name:'Homer']).save(failOnError:true)
def eval = new Evaluation([contributor:contributor, comment:'a comment']).save(failOnError:true)
contributor.evals = [eval]
contributor.save(failOnError:true)
Or this, does work:
def contributor = new Contributor([name:'Homer'])
def eval = new Evaluation([contributor:contributor, comment:'a comment'])
contributor.evals = [eval]
contributor.save(failOnError:true)
Not sure I fully understand why the top save method doesn't work when selecting data since the id of the contributor is saved on the evaluation.
精彩评论