在Bootstrap.groovy中设置Grails域ID

时间:2009-01-30 15:49:54

标签: grails gorm

是否可以在Grails的Bootstrap.groovy中显式设置域对象的id(或者就此而言在任何地方)?

我尝试了以下内容:

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

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

但是在这两种情况下,当我在运行时打印出Foo.list()的结果时,我看到我的对象的id为1,或者序列中的下一个id是。

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

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

3 个答案:

答案 0 :(得分:10)

是的,手动GORM映射:

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

和你的第二个片段(不是第一个片段)将完成这项工作(在通过构造函数传递时不会分配Id。)

答案 1 :(得分:1)

我最终使用的解决方法是不尝试通过其ID来检索对象。因此,对于问题中给出的示例,我更改了我的域对象:

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

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

然后我使用enum来保存代码的所有可能值(它们是静态的),并通过使用适当的枚举值执行Foo来检索Foo.findByCode()个对象(而不是像我之前想做的那样使用带有id的Foo.get()

这不是最优雅的解决方案,但它对我有用。

答案 2 :(得分:1)

作为替代方案,假设您正在导入数据 或从现有应用程序迁移数据 ,出于测试目的,您可以在Bootstrap文件中使用本地地图。可以把它想象成带有好处的import.sql; - )

使用这种方法:

  1. 您不需要仅为了更改域约束 测试,
  2. 您将拥有来自现有数据的经过测试的迁移路径,
  3. 您将有一个好的数据切片(或完整切片)用于将来的集成测试
  4. 干杯!

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