4

考虑以下代码:

class User {
    static constraints = {
        email email: true, unique: true
        token nullable: true
    }

    String email
    String password
    String token
}

@TestFor(User)
@TestMixin(DomainClassUnitTestMixin)
class UserSpec extends Specification {
    def "email should be unique"() {
        when: "twice same email"
        def user = new User(email: "test@test.com", password: "test")
        def user2 = new User(email: "test@test.com", password: "test")

        then: "saving should fail"
        user.save()
        !user2.save(failOnError: false)
    }
}

使用以下配置(部分配置),application.yml:

grails:
    gorm:
        failOnError: true
        autoFlush: true

为什么user2.save(failOnError: false)不返回false,因为它没有被保存到数据库中?

运行输出grails test-app *UserSpec::

businesssoftware.UserSpec > email 应该是唯一的 FAILED org.spockframework.runtime.ConditionNotSatisfiedError at UserSpec.groovy:40

当我用它替换user.save()时,user.save(flush: true)确实有效。

但是https://grails.github.io/grails-doc/latest/guide/conf.html的文档第 4.1.3 节声称:

grails.gorm.autoFlush - 如果设置为 true,则导致合并、保存和删除方法刷新会话,而不需要使用 save(flush: true) 显式刷新。

作为参考,这是以下输出grails --version

| Grails 版本:3.0.2
| Groovy 版本:2.4.3
| JVM版本:1.8.0_40

这正是我正在做的,我在这里错过了什么?

4

1 回答 1

1

我认为 autoFlush 文档具有误导性。

grails.gorm.autoFlush - 如果设置为 true,则导致合并、保存和删除方法刷新会话,而不需要使用 save(flush: true) 显式刷新。

看看 GormInstanceApi 的 save() 方法和 doSave( )。在 doSave() 快结束时,您会看到只有在 flush 参数为 true 时才会刷新会话:

if (params?.flush) {
    session.flush()
}

代码中没有任何内容表明 flush 参数可以来自任何其他地方,而不是传递给 save() 的内容。

我找不到代码来证明它,但我认为当 Hibernate 会话关闭时 autoFlush 会发挥作用,例如当控制器或服务方法存在/返回时。

此外,用于 Spock 和 JUnit 的 GORM 实现并不是真正的GORM,因此它甚至可能不使用 autoFlush 配置。

我要在这里冒险了。我还没有尝试过,但您可以手动刷新会话。

@TestFor(User)
@TestMixin(DomainClassUnitTestMixin)
class UserSpec extends Specification {
    def "email should be unique"() {
        when: "twice same email"
        def user = new User(email: "test@test.com", password: "test")
        def user2 = new User(email: "test@test.com", password: "test")
        simpleDatastore.currentSession.flush()

        then: "saving should fail"
        user.save()
        !user2.save(failOnError: false)
    }
}

simpleDataStore 来自DomainClassUnitTestMixin

于 2015-07-29T22:45:59.837 回答