Considering the following domain classes :
class EnrichmentConfig {
String name
String description
String concept
List fields = []
static hasMany = [fields: FieldConfig]
static constraints = {
name(maxSize: 60, blank: false, nullable: false, unique: true)
concept(maxSize: 255, blank: false, nullable: false)
description(nullable: true, blank: true)
fields(nullable: false, validator: { fields, enrichmentConfig ->
if (fields?.isEmpty()) {
return ['empty']
} else {
return true
}
})
}
static mapping = {
description(type: 'text')
fields(cascade: "all-delete-orphan")
sort('name')
}
}
and
class FieldConfig {
List providers = []
static hasMany = [providers: String]
static belongsTo = [mainConfig: EnrichmentConfig]
static constraints = {
providers(nullable: false, validator: { providers, fieldConfig ->
// some custom validation
})
}
static mapping = {
providers(cascade: 'all-delete-orphan', lazy: false)
}
}
Here the code I use to update an EnrichmentConfig instance in the associated controller:
def update = {
def enrichmentConfig = EnrichmentConfig.get(params.long('id'))
if (enrichmentConfig) {
enrichmentConfig.properties = params
if (enrichmentConfig.validate()) {
if (enrichmentConfig.save(flush: true, failOnError: true)) {
flash.message = "${message(code: 'enrichmentConfig.updated.message', args: [enrichmentConfig.name])}"
redirect(controller: 'enrichment')
}
} else {
// re-validation to attach an error object to each eroneous fieldConfig
enrichmentConfig.fields?.each { it.validate() }
}
render(view: 'fields', model: getFieldsModel(enrichmentConfig))
return
} else {
flash.message = "${message(code: 'enrichmentConfig.not.found.message', args: [params.id])}"
redirect(controller: 'enrichment')
}
}
I've noticed that when I validate an instance of EnrichmentConfig to be updated, associated FieldConfig instances are unexpectedly saved in the database even though they are invalid.
In fact, in debug ste-by-step mode, while enrichmentConfig.validate() is executed, the following appears in the console:
Hibernate:
update
field_config_providers
set
providers_string=?
where
field_config_id=?
and providers_idx=?
How can this be happening? What am I doing wrong? I should specify that I use grails 1.3.7.
Thanks in advance for your help.
This is just a guess but possibly someplace to start. I don't pretend to understand when Hibernate decides to flush sessions and partially save data and the like. But what I do know is that putting all write related calls in a service saves me a ton of grief over time.
Try moving some of your update method to a service and see if you have better luck. My hunch is that possibly, hibernate needs to persist some of the data to do other stuff and if it were in a transactional service, that write would rollback once the RuntimeException is thrown.