rcgeorge23
rcgeorge23

Reputation: 3694

Grails - owning side of relationship not persisted when using a List

I am experiencing a strange problem when trying to persist an association between two entities. When I use a Set (i.e. the Grails default), it works, however if I try to use a List, the association in the child table is lost somewhere between setting it in my domain class and the SQL insert statement being generated.

I've extracted the offending code from my application, and set up the simplest test case that shows the problem - it involves the 3 domain objects shown below.

class Client {
    String name
    List<ModelFieldInstance> clientModelFieldInstances
    static hasMany = [clientModelFieldInstances: ModelFieldInstance]
}

class ModelFieldDefinition {
    String name
    static hasMany = [ modelFieldInstances: ModelFieldInstance ]

    def afterInsert() {
        Client.findAll().each { client ->
            ModelFieldInstance.withNewSession {
                ModelFieldInstance modelFieldInstance = new ModelFieldInstance(['modelFieldDefinition.id': this.id, 'client.id': client.id])
                modelFieldInstance.save()
            }
        }
    }   
}

class ModelFieldInstance {
    String value
    static belongsTo = [ modelFieldDefinition: ModelFieldDefinition, client: Client ]
}

In Bootstrap.groovy, I'm creating one Client and one ModelFieldDefinition -

Client client = new Client(name: 'Some Client')
client.save(flush: true)

ModelFieldDefinition contactName = new ModelFieldDefinition([name: 'Contact Name'])
contactName.save(flush: true)

The afterInsert method in ModelFieldDefinition is used to create empty ModelFieldInstances for each Client. If I step through the afterInsert code using the STS debugger, I can see that modelFieldInstance.client has the correct value however once modelFieldInstance.save() is invoked, I get an exception saying that modelFieldInstance.client is null -

Caused by MySQLIntegrityConstraintViolationException: Column 'client_id' cannot be null

If I change my Client class, removing the List declaration like so -

class Client {
    String name
    static hasMany = [clientModelFieldInstances: ModelFieldInstance]
}

Then the association is persisted correctly. Why doesn't this work with Lists?

EDIT - I am using Grails 2.2.0

Upvotes: 1

Views: 711

Answers (1)

aiolos
aiolos

Reputation: 4697

Have a look at the GORM docs. If you use a List instead of a Set Hibernate creates a clientModelFieldInstances_idx column in your database. This column must be filled to ensure the order of objects within your List.

From the docs: When using a List, elements must be added to the collection before being saved, otherwise Hibernate will throw an exception ...

Try to use the addTo* method instead of setting the corresponding ids manually.

Upvotes: 3

Related Questions