如何创建Grails域对象但不保存?

Joh*_*ohn 2 grails hibernate grails-orm

我有一个应该创建域对象的方法.但是,如果在构建对象的过程中出现条件,则该方法应该只返回而不保存对象.

鉴于:

class SomeDomainObjectClass {
    String name
}

class DomCreatorService {
    def createDom() {
        SomeDomainObjectClass obj = new SomeDomainObjectClass(name: "name")

        // do some processing here and realise we don't want to save the object to the database
        if (!dontWannaSave) {
            obj.save(flush: true)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的测试中(服务是DomCreatorService的实例):

expect: "it doesn't exist at first" 
SomeDomainObjectClass.findByName("name") == null

when: "we attempt to create the object under conditions that mean it shouldn't be saved"
// assume that my test conditions will mean dontWannaSave == true and we shouldn't save     
service.createDom() 

then: "we shouldn't be able to find it and it shouldn't exist in the database"
// check that we still haven't created an instance
SomeDomainObjectClass.findByName("name") == null
Run Code Online (Sandbox Code Playgroud)

我的最后一行是失败的.为什么最后一个findByName返回true,即为什么我的对象可以被找到?我以为它只会找到保存到数据库中的对象.我应该测试一下,看看我的对象是否尚未创建?

Bur*_*ith 6

你必须要留下一些东西 - 如果你只是创建一个实例但不要在其上调用任何GORM方法,Hibernate就无法知道它.它开始管理对象的唯一方法是通过初始save()调用"附加"它.没有它,它就像任何其他对象一样.

@agusluc描述的是你将会看到的,但这对你没有影响的是什么.如果你加载一个先前持久化的实例并修改任何属性,在请求结束时Hibernate的脏检查将启动,检测到这个附加但未保存的实例是脏的,并且它会将更改推送到数据库,即使你没有打电话save().在这种情况下,如果您不希望持续编辑,请通过调用将会话中的对象分离discard().这与你所看到的无关,因为你没有附加任何东西.

可能name已经有一个具有该属性的实例.检查findByName查询返回的其他属性,我假设您将看到它是以前持久化的实例.

此外,这是单元测试还是集成?确保使用集成测试来实现持久性 - 单元测试模拟不是用于测试域类,它只应该用于在测试其他类型的类(例如控制器)时为域类提供GORM行为.