I have a requirement to persist the parent and children of a one-to-many relationship in one go - the domain objects in question are Project
and ProductLineItem
(a Project
has many ProductLineItem
s).
I've created a page where a user can add one or more rows to a 'products' table, and I want each row to be persisted as a new ProductLineItem
(owned by the Project
) when a user submits the form.
Saving the domain objects for the first time works great, however when I try to update the same set of objects (via the update page) I get an IndexOutOfBoundsException in the controller when doing
projectInstance.properties = params
I can fix this by declaring the productLineItems
collection in Project
like this -
Collection<ProductLineItem> productLineItems = ListUtils.lazyList(new ArrayList(), {new ProductLineItem()} as org.apache.commons.collections.Factory)
however for some reason this prevents the ProductLineItem.project
property from being populated when I do the initial save.
I'm using Grails 2.2.2. Any ideas?
It turns out that declaring the collection as a bag seems to prevent Grails setting up the foreign key constraint.
By changing
Collection<ProductLineItem> productLineItems = ListUtils.lazyList(new ArrayList(), {new ProductLineItem()} as org.apache.commons.collections.Factory)
to
List<ProductLineItem> productLineItems = ListUtils.lazyList(new ArrayList(), {new ProductLineItem()} as org.apache.commons.collections.Factory)
I was able to fix the problem.
EDIT:
For what it's worth, I didn't want to use a list (I always seem to run into issues with 'gaps' appearing when using lists for one-to-many relationship collections), so I kept fiddling around with my code.
If I declare the bag like this:
Collection<ProductLineItem> productLineItems = ListUtils.lazyList(new ArrayList(), {new ProductLineItem()} as org.apache.commons.collections.Factory)
then the reference to the parent is not set inside the child entity. However, if I declare the bag like this:
Collection productLineItems
then it works! And the collection auto-expands too!
Still testing my code, but it's looking good so far.