2010-01-15 7 views
11

Questa domanda è divisa in due parti, la prima parte riguarda la cancellazione di una lista e la seconda parte riguarda l'assegnazione di un proprietario a un oggetto.Come svuotare e sostituire una raccolta in una relazione uno-a-molti in Grails/Groovy

Ho una relazione uno-a-molti tra due oggetti dominio nel mio modello in Grails. Il rapporto si presenta così ...

class Person { 

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

class Location { 

    static belongsTo = Person 

} 

Nella mia app lista locations su Person ottiene completamente rinnovato e sostituito con un nuovo elenco su un azione dell'utente. Inoltre, viene visualizzato l'elenco degli oggetti Location indipendentemente dallo Person associato. Risolvo a quale persona applicarli recuperando l'utente attualmente connesso, che io chiamo activePerson e va bene per i miei scopi.

Quello che voglio fare è eliminare tutte le posizioni esistenti su activePerson e inserire tutte quelle nuove, associandole allo activePerson mentre procedo. Ho un sacco di proprietà su Person che non voglio mantenere a questo punto, quindi voglio evitare di salvare l'intero oggetto genitore solo perché le posizioni dei bambini sono cambiate.

Ho pensato di iterare attraverso l'elenco activePerson.locations e di eliminarli uno per uno e basandomi su GORM/Hibernate per raggruppare le query insieme e svuotare alla fine. Sembra una forza bruta, anche se potrebbe funzionare. Mi aspettavo che ci fosse un metodo clearLocations o qualcosa di simile, ma non riesco a trovarne uno.

Se si sostituisce semplicemente lo activePerson.locations con un nuovo elenco e si chiama activePerson.save(flush:true), GORM gestirà l'eliminazione delle righe esistenti?

In secondo luogo voglio mettere i nuovi oggetti Location su activePerson. Ancora una volta potrei popolare lo activePerson.locations e salvare il tutto, ma vorrei evitarlo se posso. Posso salvarli individualmente, ma come faccio a impostare belongsTo su ogni oggetto Location mentre procedo?

Quindi, per ricapitolare:

  1. Come posso eliminare un elenco alla fine molti di una collezione uno-a-molti?
  2. Come associo oggetti indipendenti con un oggetto padre e li conservo singolarmente?

Grazie

risposta

8

per # 1 è possibile cancellare la collezione (è un set di default):

activePerson.locations.clear() 

Per # 2 uso addToLocations:

activePerson.addToLocations(location) 

e quando salva la persona nella posizione < -> la relazione persona verrà aggiornata.

+0

@ Burt, grazie (ancora) per la risposta, ti devo una birra. Ciò implica tuttavia che devo mantenere l'oggetto Person, che stavo cercando di evitare. C'è un'alternativa ragionevole o dovrei semplicemente vivere con l'aggiornamento di un disco che non è davvero cambiato? – Simon

+0

Oltre alla risposta di Burt, potrebbe essere necessario implementare equals e hashcode sull'oggetto di raccolta e specificare cascade: "all-delete-orphan" sul mapping della raccolta. –

+2

'activePerson.locations.clear()' sulla raccolta non funziona. Prova: 'activePerson.locations.collect(). Each {item.removeFromLocations (it)}' – Athlan

8

Cancellazione Collection approccio non ha funzionato per me:

activePerson.locations.clear() 

Basta provare iterare sopra collezione evitando ConcurrentModificationException chiamando collect():

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

E dopo che salva l'entità di eseguire un'istruzione SQL :

activePerson.save flush:true 

Link articolo per saperne di più: http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

+0

non ha funzionato per me finché non ho specificato orphanRemoval = true sull'entità @OneToMany (..., orphanRemoval = true) – Mahakala

+2

"L'elemento" non dovrebbe essere "activePerson"? In questo modo possiamo chiamare removeFromLocations (it)? –

6

Mentre questo è una domanda più vecchio, mi sono imbattuto in una situazione molto simile in cui ho voluto aggiornare una serie di record figlio. Ecco come ho scelto di risolverlo. Per semplicità, userò gli stessi nomi oggetto/relazione del richiedente la domanda.

  1. Nel mapping blocco del dominio padre, aggiungere:

    static mapping = { 
        locations(cascade: "all-delete-orphan") 
    } 
    
  2. nel dominio figlio, aggiungere il @EqualsAndHashCode di annotazione (solo nel caso in cui ce n'è un altro in agguato su, mi riferisco a groovy.transform.EqualsAndHashCode).

  3. Aggiungere tutti gli elementi figli al dominio padre utilizzando i metodi Grails addTo (ad esempio addToLocations) e quindi salvare il dominio padre.

Anche se questo approccio non richiede il salvataggio del dominio padre (che il richiedente non ha voluto fare), sembra come se fosse l'approccio più appropriato data la chiara definizione belongsTo nel modello. Vorrei quindi rispondere alle domande numerate del Asker in questo modo:

  1. Piuttosto che farlo manualmente, diamo Grails/Hibernate cancellare i record specificando il comportamento all-delete-oprhan a cascata sulla relazione.

  2. Non tentare di salvare i record figlio direttamente, ma salvare l'oggetto padre in modo che corrisponda a ciò che sembra essere previsto da Grails.

Problemi correlati