2009-01-30 69 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)] 
    ... 
}