Search code examples
hibernategrailsgrails-ormone-to-many

Grails one-to-many relationship failing to create link back to parent when using a LazyList


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 ProductLineItems).

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?


Solution

  • 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.