Установка идентификатора домена Grails в Bootstrap.groovy - PullRequest
3 голосов
/ 30 января 2009

Можно ли явно установить идентификатор объекта домена в Booilstrap.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() во время выполнения, я вижу, что моему объекту был присвоен идентификатор 1, или каким бы ни был следующий идентификатор в последовательности.

Изменить: Это в Grails 1.0.3, и когда я запускаю свое приложение в 'dev' со встроенной базой данных HSQL.

Edit: Шанвит предоставил одно хорошее решение ниже . Тем не менее, я на самом деле искал способ установить идентификатор без изменения метода генерации идентификатора моего домена. Это в первую очередь для тестирования: я хотел бы иметь возможность устанавливать определенные значения для известных значений идентификаторов либо в моем тестовом загрузчике, либо в setUp(), но все же иметь возможность использовать auto_increment или последовательность в работе.

Ответы [ 3 ]

10 голосов
/ 31 января 2009

Да, с отображением GORM вручную:

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

и ваш второй фрагмент (не первый) выполнит работу (идентификатор не будет назначен при передаче его через конструктор).

1 голос
/ 25 января 2012

В качестве альтернативы, при условии, что вы импортируете данные или переносите данные из существующего приложения , в целях тестирования вы можете использовать локальные карты в файле Bootstrap. Думайте об этом как о 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)]
    ...
}
1 голос
/ 06 марта 2009

То, что я в конечном итоге использовал в качестве обходного пути, - это не пытаться получить объекты по их идентификатору. Таким образом, для примера, приведенного в вопросе, я изменил свой объект домена:

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

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

Затем я использовал enum для хранения всех возможных значений для кода (которые являются статическими) и получал Foo объекты, выполняя Foo.findByCode() с соответствующим значением перечисления (вместо использования Foo.get() с идентификатором, как я хотел сделать ранее).

Это не самое элегантное решение, но оно сработало для меня.

...