2009-01-30 67 views
3

是否可以在Grails的Bootstrap.groovy(或任何地方)中明确设置域对象的标识?在Bootstrap.groovy中设置Grails域标识

我已经试过如下:

new Foo(id: 1234, name: "My Foo").save() 

和:

def foo = new Foo() 
foo.id = 1234 
foo.name = "My Foo" 
foo.save() 

但在这两种情况下,当我打印出来的Foo.list()在运行时的结果,我看到我的目标一直是给定一个id,或者序列中下一个id是什么。

编辑: 这是在Grails 1.0.3中,当我在'dev'中使用内置的HSQL数据库运行我的应用程序时。

编辑: chanwit已经提供one good solution below。但是,我实际上正在寻找一种方法来设置id,而不必更改我的域的id生成方法。这主要是为了测试:我希望能够在我的测试引导程序或setUp()中将某些事物设置为已知的id值,但仍然能够使用auto_increment或生产中的序列。

回答

10

是,与手动GORM映射:

class Foo { 
    String name 
    static mapping = { 
    id generator:'assigned' 
    } 
} 

和你的第二个片段(不是第一个)将做的工作(通过构造函数时,它的ID将不会分配)。

1

我最终用作解决方法的方法是不尝试通过ID检索对象。所以对于这个问题给出的例子,我改变了我的域对象:

class Foo { 
    short code /* new field */ 
    String name 

    static constraints = { 
    code(unique: true) 
    name() 
    } 
} 

然后我用一个enum来保存所有代码的可能值(这是静态的),并且将检索Foo对象通过做Foo.findByCode()与适当的枚举值(而不是使用Foo.get()与我以前想做的id)。

这不是最优雅的解决方案,但它为我工作。

1

作为替代方案,假设你导入数据或从现有的应用程序迁移数据,你可以在引导文件中使用本地地图测试目的。认为它喜欢用import.sql好处;-)

使用这种方法:

  1. 你不需要改变你的领域约束只是 测试,
  2. 你就会有一个从现有的数据进行测试的迁移路径,并
  3. 你必须为未来的集成测试

干杯良好的数据切片(或全切片)!

def init = { servletContext -> 

    addFoos() 
    addBars() 

} 

def foosByImportId = [:] 
private addFoos(){ 
    def pattern = ~/.*\{FooID=(.*), FooCode=(.*), FooName=(.*)}/ 
    new File("import/Foos.txt").eachLine { 
     def matcher = pattern.matcher(it) 
     if (!matcher.matches()){ 
      return; 
     } 

     String fooId = StringUtils.trimToNull(matcher.group(1)) 
     String fooCode = StringUtils.trimToNull(matcher.group(2)) 
     String fooName = StringUtils.trimToNull(matcher.group(3)) 

     def foo = Foo.findByFooName(fooName) ?: new Foo(fooCode:fooCode,fooName:fooName).save(faileOnError:true) 
     foosByImportId.putAt(Long.valueOf(fooId), foo) // ids could differ 
    } 
} 

private addBars(){ 
    ... 
    String fooId = StringUtils.trimToNull(matcher.group(5)) 
    def foo = foosByImportId[Long.valueOf(fooId)] 
    ... 
}