I always forget this and always go nuts for a while. It's obvious and basic but I forget, so sue me.
Creating a one:many relationship using an ordered List, instead of the default Se, when you are ready to save the new child, you have to remember to
- Create the child
- Add the child to the parent
- Save the PARENT
You cannot first create and save the child first
then add it to the parent.
Say this is your ChildController's save() method:
RIGHT:
// Do THIS
def save = {
def childInstance = new Child(params)
Parent parent = childInstance.parent
parent.addToChildren(childInstance)
if (parent.save(flush: true) ...
WRONG:
// Don't THIS in the name of all that is holy
def save = {
def childInstance = new Child(params)
child.save(flush: true)
parent.addToChildren(child)
...
If you do it the wrong way, Grails will explode with
org.hibernate.PropertyValueException: not-null property references
a null or transient value: Child._Parent_childrenBackref
Remember: create the child, add it to the parent, and then save the
parent.
This is mentioned in the Grails Reference Documentation under
5.2.4 Sets, Lists and Maps but as an "oh by the way" and doesn't actually give you the error above (though you can also get this error as well):
When using a List, elements must be added to the collection before being saved, otherwise Hibernate will throw an exception (org.hibernate.HibernateException: null index column for collection
):