Search code examples
grailsgrails-orm

Grails clear hasMany entries and add new ones error?


I am currently working on a grails applications and I have a list of addresses that are attached to an account. Basically what I want to do is when the Account is edited is displays a current list of all the attached Addresses and then I can delete/add as many as I want from the view. When this data is captured it is picked up by the controller and what I want to do is to be able to clear all of the current Addresses from this account and then create the list again with what exists on the view, my code is below:

Account Domain:

class Account {

    String name
    Date dateCreated
    Date lastUpdated

    static hasMany = [addresses:Addresses]

    static mapping = {
        addresses cascade:"all-delete-orphan"
    }

    def getAddressesList() {
        return LazyList.decorate(
              addresses,
              FactoryUtils.instantiateFactory(Addresses.class))
    }

    static constraints = {
        name(blank:false, unique: true)
    }

}

Address Domain:

class Addresses {

    int indexVal
    String firstLine
    String postcode
    String area

    static belongsTo = [account:Account]

    static mapping = {
    }

    static transients = [ 'deleted' ]

    static constraints = {
        indexVal(blank:false, min:0)
    }


}

Account Controller:

def update() {

    def accountInstance = Account.get(params.id)
    if (!accountInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'account.label', default: 'Account'), params.id])
        redirect(action: "list")
        return
    }

    if (params.version) {
        def version = params.version.toLong()
        if (accountInstance.version > version) {
            accountInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                      [message(code: 'subscriptions.label', default: 'Subscriptions')] as Object[],
                      "Another user has updated this Account while you were editing")
            render(view: "edit", model: [accountInstance: accountInstance])
            return
        }
    }

    accountInstance.properties = params

    accountInstance.addresses.clear()
    accountInstance.save(flush: true)

    ....

}

Error:

A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses. Stacktrace follows:
Message: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.tool.Account.addresses

This error seems to be occurring in the controller on line:

accountInstance.save(flush: true)

I have tried several different way to get this to work and would really appreciate some help.


Solution

  • So it seems like you have done some work that Grails can do for you.

    class Account {
    
        String name
        Date dateCreated
        Date lastUpdated
    
        List addresses
    
        static hasMany = [addresses:Address]
    
        static mapping = {
            addresses cascade:"all-delete-orphan"
        }
    
        static constraints = {
            name(blank:false, unique: true)
        }
    
    }
    
    class Address {
        String firstLine
        String postcode
        String area
    
        static belongsTo = [account:Account]
    }
    

    This will produce the effect you want of having addresses being a list.

    I've found either

    instance.addresses = null
    

    or

    instance.addresses.clear()
    

    to work for me