Reputation: 3694
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 List
s?
EDIT - I am using Grails 2.2.0
Upvotes: 1
Views: 711
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