Sachin Sachin - 4 months ago 85
Groovy Question

Grails hasOne and hasMany with same domain and cascade operation

Is there any way of making following structure:

class Parent {
String name
static hasOne = [firstChild: Child]
static hasMany = [otherChildren: Child]
}


class Child{
String name
static belongsTo = [parent: Parent]
}


Now when i try to run a simple code:

Parent p = new Parent(name: "parent", firstChild: new Child(name: 'child'))
p.addToOtherChildren(new Child(name: "child2"));
p.addToOtherChildren(new Child(name: "child3"));
p.save(flush: true)


It saves the object but when I try to do a list operation on Parent, it throws this error:

org.springframework.orm.hibernate4.HibernateSystemException: More than one row with the given identifier was found: 2, for class: test.Child; nested exception is org.hibernate.HibernateException: More than one row with the given identifier was found: 2, for class: test.Child


The problem here is hasOne stores the Parent id in Child, as does hasMany with belongsTo, now more than one child instance has same parent id, hence it is finding difficult to decide which one is for firstChild.

I have tried this solution as well but it throws this exception:

org.springframework.dao.InvalidDataAccessApiUsageException: Not-null property references a transient value - transient instance must be saved before current operation : test.Child.parent -> test.Parent; nested exception is org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : test.Child.parent -> test.Parent


Is there any better way of doing it or am i doing anything wrong?

I want to cascade save firstChild and otherChildren with parent.

Answer

According to error message (transient), You need to save parent before adding children :

 Parent p = new Parent(name: "parent")

 if(p.save()){
     p.firstChild=new Child(name: 'child');
     p.addToOtherChildren(new Child(name: "child2"));
     p.addToOtherChildren(new Child(name: "child3"));
     p.save(flush: true)
}
Comments