2010-02-09 4 views
21

Ho una tabella con record che devono essere cancellati periodicamente in base a una serie di criteri.Come si eliminano i record di massa in Grails/GORM?

mi aspettavo che avrei potuto usare il criterio Builder per eliminare solo i record, ma che non è riuscito perché non esiste un metodo delete su criteri ...

def c = Agency.createCriteria() 
c.delete 
{ 
    eq("agency", "XXX") 
} 

Così ho pensato che forse avrei prima query per la set e quindi eliminare quella ...

def c = Agency.createCriteria() 
def deletions = c 
{ 
    eq("agency", "XXX") 
} 
deletions.delete 

Questo fallisce anche per lo stesso motivo, oggetto diverso.

Quindi qual è il modo giusto per farlo? Sembra eccessivo (perverso) che io debba ripetere l'intero set di risultati chiamando lo delete() su ciascun articolo.

So di poter creare una query da eseguire direttamente in HQL o SQL, ma anche questo sembra sbagliato. Il costruttore di criteri è pensato solo per il recupero?

Grazie

risposta

19

Dal User Guide about deleting objects:

Nota che Grails non fornisce un metodo CancTutti come la cancellazione dei dati è scoraggiati e può spesso essere evitato attraverso booleana bandiere/logica.

Se avete veramente bisogno di cancellare i dati in batch è possibile utilizzare il metodo executeUpdate fare lotti DML dichiarazioni:

Customer.executeUpdate("delete Customer c where c.name = :oldName", [oldName:"Fred"]) 
+22

sì, questo è come lo sto facendo, ma è un po 'pazzo che non posso usare criteri. DELETE è una parte valida della semantica della query e supportata da tutti gli RDBMS e una cosa perfettamente valida da fare, nonostante ciò che gli autori di Hibernate/GORM possono pensare. Nel mio caso sarebbe una pessima pratica lasciare i record non aggiornati nella tabella. – Simon

+1

come riferimenti JesperSM: Ora Grails 2+ ha un deleteAll() su DetachedCriteria. –

+3

Questo funziona. Peccato, tuttavia, che non elimina a cascata le righe nelle tabelle figlio. Quindi fornisce una 'violazione del vincolo di integrità '. Testato in '2.3.7'. – Guus

12

Se si vuole evitare HQL suggerirei usando lista GORM() , eliminare() e Groovy dell'operatore diffusione:

 
def agencyList = Agency.createCriteria().list { 
    eq("agency", "XXX") 
} 
agencyList*.delete() 
+1

Eeeek !!!cosa fa * questo randagio? Ho provato esattamente questo, ma senza * e ho ottenuto un errore del compilatore ... – Simon

+1

Il *. è l'operatore di diffusione Groovy http://groovy.codehaus.org/Operators#Operators-SpreadOperator (.) Nell'esempio di Sbglasius chiama il metodo delete() sull'elemento nella raccolta che è stato restituito. –

+0

Mi sono imbattuto in un java.util.ConcurrentModificationException quando si utilizza questo metodo ... Quindi ho smesso di usare l'operatore di spread e ho creato un ciclo while usando l'iteratore come da soluzioni in http://stackoverflow.com/questions/1816196/java- util-concurrentmodificationexception-in-non-multithreaded-program – khylo

48

Con Grails 2.0 è possibile utilizzare una query indipendente come questo:

Agency.where { }.deleteAll() 

Si noti che non si ottiene gli ascoltatori e quant'altro eseguiti, ma non esegue attraverso al database, ed è compatibile con la roba dominio deriso, come in:

void testWhatever() { 
    mockDomain(Agency, []) 
    saveABunchOfAgencies() // saves 10 of 'em 
    assert Agency.count() == 10 

    Agency.where { }.deleteAll() 

    assert Agency.count() == 0 // Joy! 
} 

Detto i banchi di prova dell'unità GORM hanno un mucchio di trucchi ma in generale sono abbastanza curati.

+0

Questo mi sembra il meglio di sicuro. Lo sto usando. – Peter

+1

Documentazione Grails per questo: http://grails.org/doc/latest/guide/single.html#whereQueries – GreenGiant

+0

Jesper, sono totalmente d'accordo con "i banchi di prova dell'unità GORM hanno un sacco di trucchi". In qualsiasi posto in cui sono documentati? –