Update上的ValidationException:在AbstractPersistenceEventListener上刷新实体时验证错误

Rog*_*ara 4 validation grails grails-orm failonerror

在我的环境中,我在Config.groovy上有grails.gorm.failOnError = true.

package org.example

class Book {

    String title
    String author
    String email

    static constraints = {
        title nullable: false, blank: false
        email nullable: false, blank: false, unique: true //apparently this is the problem..
    }
}
Run Code Online (Sandbox Code Playgroud)

而且,在控制器上,我有:

package org.example

class BookController {

def update() {

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

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

        bookInstance.properties = params

        bookInstance.validate()

        if(bookInstance.hasErrors()) {

            render(view: "edit", model: [bookInstance: bookInstance])

        } else {

            bookInstance.save(flush: true)
            flash.message = message(code: 'default.updated.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])
            redirect(action: "show", id: bookInstance.id)
        }      
    }
}
Run Code Online (Sandbox Code Playgroud)

要保存,没关系.但是,在更新时没有设置标题字段,我得到:

Message: Validation error whilst flushing entity [org.example.Book]:
- Field error in object 'org.example.Book' on field 'title': rejected value []; codes [org.example.Book.title.blank.error.org.example.Book.title,org.example.Book.title.blank.error.title,org.example.Book.title.blank.error.java.lang.String,org.example.Book.title.blank.error,book.title.blank.error.org.example.Book.title,book.title.blank.error.title,book.title.blank.error.java.lang.String,book.title.blank.error,org.example.Book.title.blank.org.example.Book.title,org.example.Book.title.blank.title,org.example.Book.title.blank.java.lang.String,org.example.Book.title.blank,book.title.blank.org.example.Book.title,book.title.blank.title,book.title.blank.java.lang.String,book.title.blank,blank.org.example.Book.title,blank.title,blank.java.lang.String,blank]; arguments [title,class org.example.Book]; default message [Property [{0}] of class [{1}] cannot be blank]

   Line | Method
->>  46 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   895 | runTask            in java.util.concurrent.ThreadPoolExecutor$Worker
|   918 | run . . . . . . .  in     ''
^   680 | run                in java.lang.Thread
Run Code Online (Sandbox Code Playgroud)

在q我理解它,问题发生在刷新hibernate会话时,hibernate尝试再次保存对象然后抛出异常...

尝试再次保存对象时,再次调用book.validate(),这会在数据库中生成新查询以确保电子邮件字段的唯一性.现在,抛出了验证异常.

但是,当我删除电子邮件属性的唯一验证时,更新正常执行..

我的问题是:这种行为是否正确?Hibernate会自动调用book.save吗?

这是示例项目,模拟错误的步骤如下:

  • 来源:https://github.com/roalcantara/grails_app_validation_exception
  • grails run-app
  • 导航到http:// localhost:8080/book/book/create
  • 创建一个填充所有字段的新实例
  • 然后编辑此实例,在:http:// localhost:8080/book/book/edit/1
  • 最后,删除'Title'字段并单击Update,然后抛出异常..

在我的环境中,这种行为发生在grails版本2.0.3和2.2.1上

谢谢你的帮助!我的可怜(又羞耻)英语让我很抱歉.. rs ..

ubi*_*con 6

你基本上是两次验证,首先是:

bookInstance.validate()
Run Code Online (Sandbox Code Playgroud)

第二个:

bookInstance.save(flush: true)
Run Code Online (Sandbox Code Playgroud)

当你打电话bookInstance.save(flush: true)给你的时候boolean.生成控制器时,Grails默认会利用此功能,但出现某种原因,您似乎已更改默认生成的控制器Grails.

只需替换这个:

    bookInstance.validate()

    if(bookInstance.hasErrors()) {

        render(view: "edit", model: [bookInstance: bookInstance])

    } else {

        bookInstance.save(flush: true)
        flash.message = message(code: 'default.updated.message', args: [message(code: 'book.label', default: 'Book'), bookInstance.id])
        redirect(action: "show", id: bookInstance.id)
    }  
Run Code Online (Sandbox Code Playgroud)

有了这个:

    if( !bookInstance.save( flush: true ) ) {
        render(view: "edit", model: [bookInstance: bookInstance])
        return
    }
Run Code Online (Sandbox Code Playgroud)