2013-03-13 70 views
3

在我的環境中,我在Config.groovy上有grails.gorm.failOnError = true。更新時出現ValidationException:驗證錯誤,同時在AbstractPersistenceEventListener上刷新實體

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 

在問:我的理解是,當沖洗Hibernate的Session,休眠試圖保存然後再次拋出異常的對象出現問題。 ..

當試圖再次保存對象時,再次調用book.validate(),這會在數據庫中新建一個查詢以確保電子郵件字段的唯一性。現在,引發驗證異常。

但是,當我刪除郵件屬性的獨特的驗證,更新正常進行..

我的問題是:這種行爲是正確的? Hibernate自動調用book.save?

這是樣板工程,並模擬了錯誤的步驟如下:

  • 來源:https://github.com/roalcantara/grails_app_validation_exception
  • Grails的運行程序
  • 導航到http://本地主機:8080 /書/書/創建
  • 創建一個新的實例填充各個領域..
  • 然後編輯這個例子中,在:HTTP://本地主機:8080 /書/電子書/編輯/ 1
  • 最後,刪除「標題」字段,然後點擊更新,然後拋出異常..

在我的環境,此行爲已發生了Grails的版本2.0.3和2.2.1

謝謝任何幫助!和我可憐的(和恥辱)英語.. RS ..

回答

5

你基本上是確認兩次,第一次與遺憾:

bookInstance.validate() 

和第二位:

bookInstance.save(flush: true) 

當你調用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) 
    } 

只需更換這

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