Validation 验证期间意外保存的grails域对象

Validation 验证期间意外保存的grails域对象,validation,grails,gorm,grails-domain-class,grails-validation,Validation,Grails,Gorm,Grails Domain Class,Grails Validation,考虑到以下域类: class EnrichmentConfig { String name String description String concept List fields = [] static hasMany = [fields: FieldConfig] static constraints = { name(maxSize: 60, blank: false, nullable: false, unique:

考虑到以下域类:

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')
    }
}

下面是我用来更新关联控制器中的
EnrichmentConfig
实例的代码:

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')
    }
}
我注意到,当我验证要更新的
EnrichmentConfig
实例时,关联的
FieldConfig
实例意外地保存在数据库中,即使它们无效。 事实上,在debug ste by step模式下,当执行
enrichmentConfig.validate()
时,控制台中会显示以下内容:

    Hibernate: 
    update
        field_config_providers 
    set
        providers_string=? 
    where
        field_config_id=? 
        and providers_idx=?
这怎么会发生?我做错了什么? 我应该指定使用Grails1.3.7


提前感谢您的帮助。

这只是一个猜测,但可能是一个开始。我并不假装理解Hibernate何时决定刷新会话和部分保存数据等。但我所知道的是,将所有与写相关的呼叫都放在一个服务中,随着时间的推移,我可以省去很多悲伤


尝试将一些更新方法移动到一个服务,看看你是否有更好的运气。我的直觉是,hibernate可能需要保存一些数据来做其他事情,如果它是在事务服务中,那么一旦抛出RuntimeException,写操作就会回滚。

这只是一个猜测,但可能是一个开始。我并不假装理解Hibernate何时决定刷新会话和部分保存数据等。但我所知道的是,将所有与写相关的呼叫都放在一个服务中,随着时间的推移,我可以省去很多悲伤


尝试将一些更新方法移动到一个服务,看看你是否有更好的运气。我的直觉是,hibernate可能需要保存一些数据来执行其他操作,如果它在事务性服务中,那么一旦抛出RuntimeException,写入操作就会回滚。

我建议使用服务来保存对象。首先,使用validate()方法检查所有对象的有效性


然后,按对象所依赖的顺序或所遵循的层次结构保存对象。

我建议使用服务保存对象。首先,使用validate()方法检查所有对象的有效性


然后,按照对象所依赖的顺序或它们所遵循的层次结构保存对象。

某些自定义验证是否在代码中实际为空,或者在此处发布时是否将其忽略?有些东西,例如动态查找器调用(
Something.findAllByFoo(…)
)会触发会话刷新,因此如果在验证器中使用类似的东西,请小心。
//某些自定义验证是否在代码中实际为空,或者在此处发布时将其忽略?有些东西,比如动态查找器调用(
Something.findAllByFoo(…)
),会触发会话刷新,所以如果在验证器中使用类似的东西,请小心。
    Hibernate: 
    update
        field_config_providers 
    set
        providers_string=? 
    where
        field_config_id=? 
        and providers_idx=?