2012-10-09 7 views
5

Eventuali duplicati:
Hibernate: different object with the same identifier value was already associated with the sessionGrails "un oggetto diverso con lo stesso valore identificativo è stato già associato alla sessione" Errore

ho il seguente codice nel mio controller in Grails che non funziona con il messaggio di errore "a different object with the same identifier value was already associated with the session". Ho già visitato alcune pagine in cui si dice che devo chiamare "merge" prima di chiamare risparmio che finisce con questo errore Provided id of the wrong type for class com.easytha.QuizTag. Expected: class java.lang.Long, got class org.hibernate.action.DelayedPostInsertIdentifier

Qualcuno ha suggerito che graal plug-in per la ricerca potrebbe essere la causa questo e dovrebbe rimuovere ricercabile = vera forma il mio dominio classe che non è un'opzione (fare riferimento al post precedente qui grails searcheable plugin search in inner hasMany class)

Una cosa da sottolineare è che l'errore non viene generato al momento della chiamata di q.save() piuttosto che viene generato durante il richiamo del reindirizzamento redirect (azione: " spettacolo", id: id) !!

Qualche suggerimento?

def addTags(String tags,Long id){ 
     if(tags){ 
      String[] strTags = tags.split(","); 
      Quiz q = Quiz.get(id)   
      for(String t in strTags){ 
       Tag tagToAdd = Tag.findByTag(t) 

       if(!tagToAdd){ 
        tagToAdd = new Tag(tag:t) 
        tagToAdd.save() 
       } 

       println "---> "+tagToAdd +" Quiz"+q?.id 
       def qt = QuizTag.findByQuizAndTag(q,tagToAdd) 
       if(!qt){ 
        qt = new QuizTag(quiz:q,tag:tagToAdd); 
        q.addToTags(qt) 
       } 

      }   
      q.save()   
      redirect(action:"show",id:id) 
     } 
    } 

----------- EDIT ---------------

Final code that worked with searchable plugin 
     def addTags(String tags,Long id){ 
     if(tags){ 
      String[] strTags = tags.split(","); 
      Quiz q = Quiz.get(id)   
      for(String t in strTags){ 
       if (q.tags.any { QuizTag qt -> qt.tag.tag == t }) { continue; } 
        Tag tagToAdd = Tag.findOrSaveByTag(t); 
        QuizTag qt = new QuizTag(quiz:q,tag:tagToAdd) 
        q.addToTags(qt) 
       }   
      q.save(flush:true)  
      redirect(action:"show",id:id) 
     } 
    } 
+1

Dalla descrizione del metodo save(): "L'oggetto non verrà persistito immediatamente se non si utilizza l'argomento a filo" Ecco perché l'errore si verifica solo al termine della richiesta. –

+0

@TiagoFarias hai ragione. dopo aver chiamato q.save (flush: true) ottengo l'errore giusto su quella linea, l'altra cosa da notare qui è che anche dopo l'errore i miei dati vengono ancora salvati! Anche questo errore si verifica solo se il tag esiste già che significa "Tag.findByTag (t)" restituisce qualcosa – Sap

risposta

0

Grails di default carica lazy collezioni con proxy Hibernate. Quindi forse si duplicano i proxy QuizTag (o i proxy e gli oggetti gonfiati) che causano il problema.

Si potrebbe provare qualcosa di simile:

Quiz q = Quiz.get(id)   
for(String t in strTags){ 
    // Check if the tag is already joined to this quiz and 
    // skip a dynamic finder load later 
    if (q.tags.any { QuizTag qt -> qt.tag.tag == t }) { continue; } 
    // Find or create-save the tag to join 
    Tag tagToAdd = Tag.findOrSaveByTag(t); 
    QuizTag qt = new QuizTag(quiz:q,tag:tagToAdd) 
    qt.save() 
    q.addToTags(qt) 
} 
+0

Beh, il mio codice di cui sopra funzionato ma ora non indicizza i tag e quiz !! quindi niente risultati della ricerca :) – Sap

+0

il comportamento sembra così casuale, ha iniziato a lavorare solo un momento fa, ma ora lo stesso errore quando si chiama q.save (flush: true) – Sap

3

dal momento che non Quiz.get(id), si dispone di un ' connesso 'istanza, quindi non è necessario' unire '- che è solo per ricollegare un'istanza disconnessa.

Penso che la ragione che hai trovato l'errore è che la linea:

def qt = QuizTag.findByQuizAndTag(q, tagToAdd) 

tira l'istanza QuizTag nella sessione, ma Tag tagToAdd = Tag.findByTag(t) ha già associato l'istanza con la sessione, e si sta assegnando a un'altra variabile. Ora ci sono due istanze associate alla sessione, entrambe che rappresentano la stessa riga nel database, qt e tagToAdd (hanno lo stesso ID). Ciò produce una situazione ambigua e non è consentita, quindi l'errore.

Sembra che non sia effettivamente necessario creare un'istanza qt (si agisce solo se non esiste). Quindi, suggerirei di fare una query per scoprire se esiste (forse un 'select count') invece di recuperare effettivamente l'istanza dell'oggetto. In questo modo, avrai solo una copia dell'oggetto.

+0

Come da tuo suggerimento non dovrebbe funzionare il nuovo codice in "EDIT"? – Sap

+0

Mi dispiace, non capisco la tua domanda. Cos'è "il nuovo codice in EDIT"? – GreyBeardedGeek

+0

:) Intendo l'area modificata nel post originale. Dove ho cambiato l'assegnazione variabile a Tag tagToAdd = Tag.findByTag (t) ?: nuovo tag (tag: t) e def qt = QuizTag.findByQuizAndTag (q, tagToAdd) ?: nuovo QuizTag (quiz: q, tag: tagToAdd); Non pensi che avrebbe potuto funzionare! – Sap

Problemi correlati