为什么Grails似乎在保存我的无效域对象?

时间:2015-06-27 00:53:58

标签: grails gorm

我正在使用Grails 2.4.2。我正在保存违反约束的域类实例,所以我希望保存失败。但它似乎成功了。 Grails文档说明:

  

要记住的另一件事是Grails每次保存时都会验证域实例。如果验证失败,域实例将不会持久保存到数据库。

域类:

class Book {
    String name
    static constraints = {
        name unique: true
    }
    String toString() { "[Book: id=${id} name=${name}]" }
}

以下代码修改第二个实例,使其与第一个实例具有相同的名称并尝试保存它(book3.save)。我希望这会失败,它确实返回null。但后来我通过Id(Book.get(book2.id))加载了同一个对象,并发现它有新名称。最后,它打印整个书籍列表,我们发现它们都有相同的名称。

    def book1 = new Book(name: "Cats").save()
    def book2 = new Book(name: "Dogs").save()
    log.info "The books: ${Book.list()}"
    def book3 = Book.get(book2.id)
    book3.name = "Cats"
    def book3save = book3.save() // Should fail?
    def book4 = Book.get(book2.id)
    log.info "The result of saving book ${book2.id} with name 'Cats' is ${book3save}"
    log.info "The book with ID ${book2.id} is now named ${book4.name}"
    log.info "The books are: ${Book.list()}"

输出:

The books: [[Book: id=1 name=Cats], [Book: id=2 name=Dogs]]
The result of saving book 2 with name 'Cats' is null
The book with ID 2 is now named Cats
The books are: [[Book: id=1 name=Cats], [Book: id=2 name=Cats]]

1 个答案:

答案 0 :(得分:0)

默认情况下,Grails不会在验证错误上抛出异常。你可以做到

book3.save(failOnError: true)

将抛出异常。

或者您需要检查save()的返回值。 null表示验证失败。您还可以执行book3.validate()以在尝试保存之前查看实例是否有效。

我认为你所看到的正在更新的书的外观是由于hibernate会话。您的保存失败但是对Book.get()的调用从当前的hibernate会话而不是数据库加载实例。如果检查脏标志,则可以确认此检查isDirty()或调用refresh()以从数据库中重新获取实例。