5

私の環境では、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..
    }
}

そして、コントローラーでは、私は持っています:

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

保存するために、それは大丈夫です。しかし、タイトルフィールドを設定せずに更新すると、次のようになります。

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

qで私はそれを理解しています、フラッシュ休止状態セッションで問題が発生し、休止状態がオブジェクトを再度保存しようとすると、例外がスローされます...

オブジェクトを再度保存しようとすると、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
  • 最後に、[タイトル]フィールドを削除し、[更新]をクリックすると、例外がスローされます。

私の環境では、この動作はgrailsバージョン2.0.3および2.2.1で発生しました。

助けてくれてありがとう!そして、私の貧しい(そして恥ずべき)英語でごめんなさい..rs ..

4

1 に答える 1

6

あなたは基本的に2回検証しています。最初に:

bookInstance.validate()

そして2番目に:

bookInstance.save(flush: true)

呼び出すとbookInstance.save(flush: true)abooleanが返されます。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)
    }  

これとともに:

    if( !bookInstance.save( flush: true ) ) {
        render(view: "edit", model: [bookInstance: bookInstance])
        return
    }
于 2013-03-14T01:44:13.063 に答える