views:

32

answers:

1

Hi,

I am stuck at this problem. The code looks ok to me(obviously I am missing something. The question is what it is?)

I have a Project class

def class project{
    ...
    Manager manager
 }

This is Person and Manager class definition

def class Person{
   String firstName
   String lastName
}

def class Manager extends Person{
   static hasMany = [ projects: Project]

}

The relationship is simple - A Project has one manager and a manager has many projects. As far as I know, in the one-to-many relationship the save cascades because it is bi-directional one-to-many. But when I do this

Project project = new Project()
Manager mgr = new Manager(...)
project.manager = mgr
project.save()

I get the following error Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Manager

and when I do this

Project project = new Project()
Manager mgr = new Manager(...)
project.manager = mgr
project?.manager.save()
project.save()

It works just fine. But I think project?.manger.save() shouldn't be required!!

+1  A: 

A quick fix would be to save the manager before saving the project.

You also don't have a belongsTo setup. Check out chapter 5 of the grails documentation.

http://grails.org/doc/latest/

"In the case of a bidirectional one-to-many where the many side does not define a belongsTo then the cascade strategy is set to "SAVE-UPDATE" for the one side and "NONE" for the many side."

So, if i get this correctly, you can call save on the mgr (the one side) but not save on the project side (to get cascading to work)

In the case of a bidirectional one-to-many where the many side defines a belongsTo then the cascade strategy is set to "ALL" for the one side and "NONE" for the many side.

You will also want to check out section 5.5.2.9, where you can specify custom cascading behavior.

hvgotcodes
Thanks for your answer. Yes saving manager first does the trick. But belongsTo doesn't help. Which is the right way to do thati) Remove Manager manager and just having static belongsTo = [manager: Manager] or static belongsTo = Managerii) Keeping both Manager manager and having static belongsTo = [manager: Manager] or static belongsTo = Manager.BTW, I tried both and it doesn't work. For now the quick fix is working
Paras
hmm I think the right way is to save the one side. "In the case of a bidirectional one-to-many where the many side defines a belongsTo then the cascade strategy is set to "ALL" for the one side and "NONE" for the many side." Even with the belongsTo, the cascade is NONE for the many side. Saving the many side first won't work if the one side isn't persistent yet. I think this makes sense, because typically you would add a manager to the system, save it, then add projects. Although I could see the case where you would do both in the same go.
hvgotcodes