2014-12-19 101 views
2

我有一个应该创建一个域对象的方法。但是,如果在构建对象的过程中出现条件,则该方法应该返回并且不保存该对象。如何创建Grails域对象但不保存?

考虑:

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) 
     } 
    } 
} 

我的测试中(服务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 

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

回答

5

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

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

可能有一个name属性的实例。检查findByName查询返回的其他属性,我假设你会看到它是以前持久化的实例。

此外,这是一个单元测试或集成?一定要使用集成测试来保持持久性 - 单元测试模拟不是用于测试域类,它只能用于在测试其他类(例如控制器)时将GORM行为提供给域类。

+0

你是完全正确的,谢谢。这个错误是因为我在一个EachWithIndex闭包中进行了更改,然后调用了返回值,认为闭包后的保存调用不会被调用。我现在意识到,闭包内的返回调用不会从包含闭包的方法返回,它只从闭包本身返回。 – John

+0

@Burt谢谢,救了我一天。我在搜索一个Domain类命令对象如何在脏时被持久化,在grails文档命令对象部分进行搜索,但在这里更加清楚。我认为这应该在那里,或者我错过了一些东西。 –