2010-01-15 5 views
11

Diese Frage besteht aus zwei Teilen, der erste Teil ist über das Löschen einer Liste und der zweite Teil über das Zuweisen eines Eigentümers zu einem Objekt.Wie lösche und ersetze ich eine Sammlung in einer Eins-zu-viele-Beziehung in Grails/Groovy

Ich habe eine Beziehung zwischen zwei Domäne-Objekten in meinem Modell in Grails eine Eins-zu-viele Beziehung. Die Beziehung sieht wie folgt aus ...

class Person { 

    static hasMany = [authorities: Role, locations: Location] 
} 

class Location { 

    static belongsTo = Person 

} 

In meiner app die locations Liste auf Person wird vollständig erneuert und mit einer neuen Liste auf eine Aktion des Benutzers ersetzt. Was mehr ist, bekomme ich die Liste der Location Objekte unabhängig von der zugehörigen Person. Ich entscheide, welche Person sie anwenden soll, indem ich den aktuell angemeldeten Benutzer abrufe, den ich activePerson rufe und für meine Zwecke in Ordnung ist.

Was ich tun möchte, ist alle vorhandenen Positionen auf activePerson löschen und fügen Sie alle neuen hinzu, sie mit der activePerson assoziieren, wie ich gehe. Ich habe eine Reihe von Eigenschaften auf Person, die ich an dieser Stelle nicht beibehalten möchte, also möchte ich vermeiden, das gesamte Elternobjekt zu speichern, nur weil Standorte Kinder geändert haben.

Ich dachte daran, die activePerson.locations Liste zu durchlaufen und sie nacheinander zu löschen und auf GORM/Hibernate angewiesen zu sein, die Abfragen zusammenzufassen und am Ende zu bündeln. Dies scheint wie rohe Gewalt, obwohl es funktionieren könnte. Ich habe erwartet, dass es eine clearLocations Methode oder etwas ähnliches gibt, aber ich kann keine finden.

Wenn ich nur die activePerson.locations durch eine neue Liste ersetzen und activePerson.save(flush:true) aufrufen, wird GORM das Löschen der vorhandenen Zeilen behandeln?

Zweitens möchte ich die neuen Location Objekte auf activePerson setzen. Wieder konnte ich die activePerson.locations bevölkern und das Ganze retten, aber ich würde das gerne vermeiden, wenn ich kann. Ich kann sie einzeln speichern, aber wie setze ich belongsTo auf jedes Location Objekt, wie ich gehe?

So zu rekapitulieren:

  1. Wie lösche ich eine Liste an der viele Ende einer Eins-zu-viele-Sammlung?
  2. Wie verknüpfe ich unabhängige Objekte mit einem übergeordneten Objekt und behalte sie einzeln?

Dank

Antwort

8

Für 1 # Sie die Sammlung löschen kann (es ist ein standardmäßig Set):

activePerson.locations.clear() 

Für # 2 Verwendung addToLocations:

activePerson.addToLocations(location) 
Sie

und wenn Speichern Sie die Person den Standort < -> Personenbeziehung wird aktualisiert.

+0

@Burt, danke (nochmal) für deine Antwort, ich schulde dir ein Bier. Dies bedeutet jedoch, dass ich das Person-Objekt beibehalten muss, was ich vermeiden wollte. Gibt es eine vernünftige Alternative oder sollte ich nur mit der Aktualisierung eines Datensatzes leben, der sich nicht wirklich verändert hat? – Simon

+0

Zusätzlich zu Burt's Antwort müssen Sie möglicherweise equals und hashcode für das Sammlungsobjekt implementieren und kaskade angeben: "all-delete-orphan" für die Zuordnung der Sammlung. –

+2

'activePerson.locations.clear()' auf der Sammlung wird nicht funktionieren. Versuchen Sie: 'activePerson.locations.collect(). Je {item.removeFromLocations (it)}' – Athlan

8

Collection Ansatz Clearing nicht für mich gearbeitet:

activePerson.locations.clear() 

Probieren Sie iterieren Sammlung mit ConcurrentModificationException Vermeidung von collect() Aufruf:

activePerson.locations.collect().each { 
    item.removeFromLocations(it) 
} 

Und danach die Entität speichern SQL-Anweisung auszuführen :

activePerson.save flush:true 

Link zum Artikel liest mehr: http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

+0

es für mich funktioniert hat, bis ich orphanRemoval = True für die Entität @ OneToMany (..., orphanRemoval = true) – Mahakala

+2

Sollte 'item' nicht 'activePerson' sein? So können wir removeFromLocations (it) aufrufen? –

6

Während dies ist eine ältere Frage, ich lief in eine sehr ähnliche Situation, in der ich eine Reihe von untergeordneten Datensätze aktualisieren wollte. Hier ist, wie ich entschied, es zu lösen. Der Einfachheit halber verwende ich die gleichen Objekt-/Beziehungsnamen wie der Fragesteller der Frage.

  1. Im mapping Block der übergeordneten Domäne hinzufügen:

    static mapping = { 
        locations(cascade: "all-delete-orphan") 
    } 
    
  2. In der untergeordneten Domäne, fügen Sie die @EqualsAndHashCode Anmerkung (nur für den Fall gibt es ein anderes lauern, ich bin auf groovy.transform.EqualsAndHashCode).

  3. Fügen Sie alle untergeordneten Elemente der übergeordneten Domäne mit den Grails addTo-Methoden hinzu (z. B. addToLocations), und speichern Sie dann die übergeordnete Domäne.

Während dieser Ansatz die übergeordnete Domäne Speicher erfordert (was die Fragesteller tun wollten nicht), so scheint es, wie es der geeignetste Ansatz der klare belongsTo Definition im Modell gegeben ist. Daher möchte ich die Fragesteller die nummerierten Fragen wie diese beantworten:

  1. Anstatt es manuell zu tun, lassen Sie Grails/Hibernate die Datensätze löschen, indem Sie die all-delete-oprhan Kaskade Verhalten auf der Beziehung angeben.

  2. Versuchen Sie nicht, die untergeordneten Datensätze direkt zu speichern, sondern speichern Sie das übergeordnete Objekt so, dass es dem entspricht, was Grails zu erwarten scheint.