更新时未保存 Grails 布尔字段

Grails boolean field not saved when updated

我有一个模型有两个 类 A 和 B,它们都有一个 "boolean lastVersion" 字段

Class "A" 有关联 "B b",在 A.beforeInsert/beforeUpdate 上,A.lastVersion 的值被复制到 B.lastVersion。

A.lastVersion 和 B.lastVersion 的默认值为真。当我将 a.lastVersion 更改为 false 并执行 a.save() 时,lastVersion 均未设置为 false。如果我做 a.save(flush:true) 只有 a.b.lastVersion 被保存为 false;

对这里的问题有什么想法吗?

我已经使用 H2 数据库在 v2.1.0 和 v2.3.7 上对此进行了测试。编辑:在 MySQL 上测试,得到相同的行为。

Here 您可以找到这两个示例应用程序(代码也包含在下面)。当 运行 应用程序并检查 H2 dbconsole 时会发生奇怪的行为。有一个名为 VersionTests 的单元测试也得到不一致的行为 IMO。

package testbools
class Version {

    static constraints = {
        ci (nullable: true)
    }

    boolean lastVersion = true
    CompositionIndex ci

    def beforeInsert() {
      this.ci.lastVersion = this.lastVersion
   }
   def beforeUpdate() {
      this.ci.lastVersion = this.lastVersion
   }
}



package testbools 
class CompositionIndex {

    static constraints = {
    }

    boolean lastVersion = true

    static belongsTo = [Version]
}

测试:

package testbools 
import grails.test.mixin.*
import org.junit.*

/**
 * See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
 */
@TestFor(Version)
class VersionTests {

    void testSomething() {

       def v = new Version(ci: new CompositionIndex())
       if (!v.save()) println v.errors

       def vget = Version.get(1)
       assert vget.lastVersion
       assert vget.ci.lastVersion

       // change value
       vget.lastVersion = false
       if (!vget.save()) println vget.errors


       // value has been changed?
       assert !vget.lastVersion
       assert !vget.ci.lastVersion


       // value has been stored?
       def vget2 = Version.get(1)
       assert !vget2.lastVersion
       assert !vget2.ci.lastVersion
    }
}

我已经从 testbools237 文件中添加了你的源代码,以便其他人更容易查看源代码,但我没有足够的声誉来批准编辑,所以也许是原始海报或者其他人可以查看和更新​​。

您正在单元测试中创建一个新的 CompositionIndex,但它没有被模拟,所以我认为您的测试不会按预期工作。我会尝试通过以下方式创建协作者:

@Mock(CompositionIndex)

在此注释下:

@TestFor(Version)

此处有详细信息:http://grails.github.io/grails-doc/2.4.3/guide/testing.html#unitTesting - 请参阅标题为测试混合基础的部分。

编辑:

最后一点,您还需要确保在进行测试断言之前,您正在编辑的域模型已实际保存到数据库中。在域 object 上调用 save() 实际上并不意味着 object 已保存,它只是意味着您已经说过要保存它。 Peter Ledbrook 解释得很好 here.

如果您在失败的测试断言之前更改您的保存:

if (!vget.save()) println vget.errors

对此:

if (!vget.save(flush: true)) println vget.errors

那么您的测试应该会按预期运行(无论如何,您失败的测试现在在我的机器上通过了)。