2012-10-09 27 views
5

Duplicar posibles:
Hibernate: different object with the same identifier value was already associated with the sessiongriales "un objeto diferente con el mismo valor de identificador ya se asoció con la sesión" error

tengo el siguiente código en mi regulador en Grails que está fallando con el mensaje de error "a different object with the same identifier value was already associated with the session". que ya han visitado algunas páginas donde dice que debo llamar "merge" antes de llamar a save que termina con este error Provided id of the wrong type for class com.easytha.QuizTag. Expected: class java.lang.Long, got class org.hibernate.action.DelayedPostInsertIdentifier

Alguien ha sugerido que griales plugin de búsqueda podría ser la causa de esto y yo debería eliminar búsquedas = verdadera forma de mi dominio clase que no es una opción (consulte la publicación anterior aquí grails searcheable plugin search in inner hasMany class)

Una cosa a señalar es que el error no se produce en el momento de llamar a q.save() sino que se produce al llamar a redirigir redirigir (acción: " mostrar ", id: id) !!

¿Alguna sugerencia?

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) 
     } 
    } 

----------- --------------- EDITAR

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

partir de la descripción del método save(): "El objeto no se persistió inmediatamente a menos que se utiliza el argumento ras." Es por eso que el error solo ocurre cuando la solicitud finaliza. –

+0

@TiagoFarias tienes razón. después de llamar a q.save (flush: true) recibo el error en esa línea, otra cosa que hay que tener en cuenta es que incluso después del error, ¡aún se guardan mis datos! Además, este error solo se produce si la etiqueta ya existía, lo que significa que "Tag.findByTag (t)" devuelve algo – Sap

Respuesta

0

Grails de forma predeterminada cargas lazy colecciones con proxies Hibernate. Entonces quizás se estén creando duplicados QuizTag proxies (o proxies y objetos inflados), lo que está causando su problema.

Usted podría intentar algo como:

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

Bueno, mi código anterior funcionó, pero ahora no está indexando las etiquetas y el cuestionario !! por lo que no hay resultados de búsqueda :) – Sap

+0

El comportamiento parece tan aleatorio, comenzó a funcionar hace un momento, pero ahora el mismo error al llamar a q.save (flush: true) – Sap

3

ya que haces Quiz.get(id), que tiene un " instancia 'conectada', por lo que definitivamente no necesita 'combinar' - eso es solo para volver a conectar una instancia desconectada.

creo que la razón de que está recibiendo el error es que la línea:

def qt = QuizTag.findByQuizAndTag(q, tagToAdd) 

tira la instancia QuizTag en la sesión, pero Tag tagToAdd = Tag.findByTag(t) ya ha asociado la instancia con la sesión, y está asignando a otra variable. Ahora tiene dos instancias asociadas a la sesión, ambas representan la misma fila en la base de datos, qt y tagToAdd (tienen la misma identificación). Esto produce una situación ambigua, y no está permitido, de ahí el error.

Parece que en realidad no necesita qt para crear una instancia (solo toma medidas si no existe). Entonces, sugeriría hacer una consulta para averiguar si existe (tal vez un 'select count') en lugar de recuperar la instancia del objeto. De esta forma, solo tendrás una copia del objeto.

+0

Según su sugerencia, ¿no debería funcionar el nuevo código en "EDIT"? – Sap

+0

Lo siento, no entiendo su pregunta. ¿Qué es "el nuevo código en EDIT"? – GreyBeardedGeek

+0

:) Me refiero al área editada en la publicación original. Donde cambié la asignación de variables a Tag tagToAdd = Tag.findByTag (t) ?: new Tag (tag: t) y def qt = QuizTag.findByQuizAndTag (q, tagToAdd) ?: nuevo QuizTag (cuestionario: q, tag: tagToAdd); ¿No crees que eso podría haber funcionado? – Sap

Cuestiones relacionadas