Установка идентификатора домена Grails в Bootstrap.groovy

Можно ли явно установить идентификатор объекта домена в Grails Bootstrap.groovy (или где-либо еще, если на то пошло)?

Я пробовал следующее:

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.

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


person Rob Hruska    schedule 30.01.2009    source источник


Ответы (3)


Да, с ручным сопоставлением GORM:

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

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

person Community    schedule 31.01.2009

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

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

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

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

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

person Rob Hruska    schedule 06.03.2009

В качестве альтернативы, если вы импортируете данные или переносите данные из существующего приложения, в целях тестирования вы можете использовать локальные карты в файле 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)]
    ...
}
person Volt0    schedule 25.01.2012