1
votes

I have a parent table Parent and a child table Child. The relation is like this:

class Parent {
   ...
   Child child

   static mapping = {
      child lazy: false, cascade: 'all'
   }
   static constraints = { ... }
}

class Child {
   String name

   static constraints = {
      name unique: true
   }
}

I created some code to add a child to an existing parent. It looks like this:

def parent = Parent.get(id)
parent.child = new Child(name: (name))
parent.save()

This code is contained in a method of transactional service.

It does not work when child is invalid - no validation happens. I get a famous hibernate error:

object references an unsaved transient instance - save the transient instance before flushing`.

It can be easily explained: child is not validated, when GORM saves objects, it tries to save child, then it should stop due to a failure, but it proceeds and tries to save parent with unsaved child field.

How can I work around the case when child is invalid? I need to propagate information about the error to a view form.

I've already tried to validate child manually - it's errors field contains 1 error, but parent is still valid. I've tried to insert the error to the parent errors field - parent becomes invalid, but GORM still tries to save it.

2

2 Answers

1
votes

Do you have belongsTo defined (e.g static belongsTo = [Parent]) in your relationship between Child and Parent? If you do not, Grails will not cascade the save/update from the Parent to the Child since it doesn't "own" the Child - thus if no save is happening on the Child, then validation never gets called. So try adding

static belongsTo = [Parent]

in the Child class and saving again, possibly with deepValidate:true as well if you're still not seeing the Child validation occurring.

-1
votes

Thanks for this nice Answer i was facing same problem due to your post i resolve the problem

def val = (params.company).toInteger()
def parent = Company.get(val)
        .addToJobs(new Job(
            experience:params.months,
            jobdescription:params.desc,
            joblocation:params.companyloc,
            jobskills:params.skills,
            jobtype:params.emp,
            salary:params.jobsalary,
            jobtitle:params.jobtitle))
        .save()