hibernategrailsgroovygrails-searchable

Grails "a different object with the same identifier value was already associated with the session" error


Possible Duplicate:
Hibernate: different object with the same identifier value was already associated with the session

I have the following code in my controller in Grails that is failing with "a different object with the same identifier value was already associated with the session" error message. I have already visited few pages where it says that I must call "merge" before calling save which ends up with this error Provided id of the wrong type for class com.easytha.QuizTag. Expected: class java.lang.Long, got class org.hibernate.action.DelayedPostInsertIdentifier

Someone has suggested that grails searchable plugin might be causing this and I should remove searchable = true form my domain class which is not an option (refer to the previous post here grails searcheable plugin search in inner hasMany class)

One thing to point is that error is not thrown at the time of calling q.save() rather it's thrown while calling redirect redirect(action:"show",id:id)!!

Any suggestions?

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

Solution

  • Grails by default lazy loads collections with Hibernate proxies. So maybe duplicate QuizTag proxies (or proxies and inflated objects) are being created, which is causing your issue.

    You could try something like:

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