2016-04-01 7 views
0

Ich habe zwei Domänenklassen CGroup und Directory, Ich möchte eine CGroup modellieren, die viele Verzeichnisse hat, jedoch ist eines dieser vielen Verzeichnisse als "root" bekannt, und ist direkt zugänglich von der CGroup. Jede CGroup sollte immer nur eine Wurzel haben, und Kaskaden sollten immer so funktionieren, dass das Löschen eines beliebigen Verzeichnisses alle seiner untergeordneten Elemente löscht.GORM Direktzugriff auf Instanz in einer hasMany-Beziehung

Obwohl falsch, das ist, was ich bisher habe:

class CGroup{ 
    ... 
    Directory root 

    static hasMany = [directory:Directory] 

    static constraints = { 
     root(unique:true) 
    } 
} 

class Directory { 

    static hasMany = [children:Directory] 
    ... 
    static belongsTo = [parent:Directory, 
         cgroup:CGroup] 

    static constraints = { 
     parent nullable: true 
    } 
} 

im Grunde, ich brauche nur einen Verweis auf eine Instanz von der „n“ Sammlung, gespeichert in der „einer Seite“

Antwort

1

Ich habe es auf verschiedene Arten versucht und die einzige Möglichkeit, es zum Laufen zu bringen, war es, root zeitweilig null zu lassen. Das Problem, das ich ohne dies hatte, war aufgrund der Bestellung - seit Directory Instanzen sind in der hasMany können sie nicht gespeichert werden, bis die CGroup gespeichert wird oder der save() Aufruf wird fehlschlagen, weil cgroup ist Null (dies ist beim Aufruf addToDirectory eingestellt). Aber Sie können die CGroup nicht speichern, ohne ihre Eigenschaft root zu setzen, wenn sie nicht nullfähig ist.

Also machte ich root nullable aber eine benutzerdefinierte Validator hinzugefügt, die Validierung fehlschlägt, wenn root null ist, und es gibt keine Instanzen im hasMany:

static constraints = { 
    root nullable: true, validator: { Directory root, CGroup cgroup -> 
     if (!root && cgroup.directory?.size()) { 
     return ['root.required'] 
     } 
    } 
} 

So würden Sie die CGroup Instanz mit allen erforderlichen Werte speichern und ohne alle zugehörigen Directory Instanzen. Dann fügen Sie die Directory Instanzen mit addToDirectory und stellen Sie die root Instanz mit dem benutzerdefinierten Setzer:

void setRoot(Directory root) { 
    if (this.root) { 
     removeFromDirectory this.root 
    } 

    if (root) { 
     addToDirectory root 
    } 

    this.root = root 
} 

und speichern Sie sie wieder:

def group = new CGroup(...).save() 

group.root = new Directory(...) 
group.addToDirectory(new Directory(...)) 
group.addToDirectory(new Directory(...)) 
group.save() 

g1.errors 
+0

Ja! Das ist genau das, wonach ich gesucht habe. Das von Ihnen angegebene Bestellproblem war das genaue Problem, dem ich gegenüber stand, aber ich war nicht so vertraut mit benutzerdefinierten Validatoren. Außerdem dachte ich, dass ich etwas Offensichtliches vermisst hätte, da es sich dabei um ein ziemlich häufiges Szenario handelte. Eine Sache, in Ihrem letzten Block von Code sollte nicht das zweite AddToDirectory tatsächlich ein Aufruf von SetRoot sein? Prost – Alexjjsmith

+1

Nein, root wird zuerst gesetzt und dann gibt es zwei zusätzliche Instanzen für insgesamt 3 hinzugefügt. Die Reihenfolge spielt keine Rolle, solange Sie beim zweiten Aufruf von save() das zweite Mal root setzen und diese Instanz ist in the hasMany, optional zusammen mit einigen zusätzlichen Instanzen. –