2009-01-30 5 views
3

Est-il possible de définir explicitement l'ID d'un objet de domaine dans Bootstrap.groovy de Grails (ou n'importe où, d'ailleurs)?Définition de l'ID de domaine Grails dans Bootstrap.groovy

J'ai essayé ce qui suit:

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

et:

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

Mais dans les deux cas, quand j'imprimer les résultats de Foo.list() lors de l'exécution, je vois que mon objet a été donné un identifiant de 1, ou quel que soit l'identifiant suivant de la séquence.

Edit: Ceci est en Grails 1.0.3, et quand je suis en mon application dans « dev » avec la base de données HSQL intégré.

Éditer: chanwit a fourni one good solution below. Cependant, je cherchais un moyen de définir l'identifiant sans changer la méthode de génération d'identifiant de mon domaine. Ceci est principalement pour tester: Je voudrais être en mesure de définir certaines choses à des valeurs id connues dans mon bootstrap de test ou setUp(), mais toujours être en mesure d'utiliser auto_increment ou une séquence en production.

Répondre

10

Oui, avec la cartographie manuellement GORM:

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

et votre deuxième extrait (non le premier) fera le travail (Id ne sera pas affecté lors de son passage à travers constructeur).

1

Ce que j'ai fini par utiliser comme une solution de contournement était de ne pas essayer de récupérer des objets par leur identifiant. Donc, pour l'exemple donné dans la question, j'ai changé mon objet de domaine:

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

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

J'ai ensuite utilisé un enum pour contenir toutes les valeurs possibles pour le code (qui sont statiques) et récupérerait Foo objets en faisant une Foo.findByCode() avec la valeur enum appropriée (au lieu d'utiliser Foo.get() avec l'id comme je voulais faire précédemment).

Ce n'est pas la solution la plus élégante, mais cela a fonctionné pour moi.

1

Comme alternative, en supposant que vous importez des données ou la migration des données d'une application existante, à des fins de test, vous pouvez utiliser des cartes locales dans le fichier Bootstrap. Pensez-y comme un import.sql avec des avantages ;-)

En utilisant cette approche:

  1. vous auriez pas besoin de changer vos contraintes de domaine juste pour les tests ,
  2. vous aurez une testé chemin de migration à partir des données existantes et
  3. vous aurez une bonne tranche de données (ou tranche complète) pour les tests d'intégration futurs

Cheers!

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