Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)
        }
    }
like image 910
Sap Avatar asked Oct 06 '22 09:10

Sap


1 Answers

Since you do Quiz.get(id), you have a 'connected' instance, so you definitely do not need to 'merge' - that's only to re-connect a disconnected instance.

I think that the reason that you are getting the error is that the line:

def qt = QuizTag.findByQuizAndTag(q, tagToAdd)

pulls the QuizTag instance into the session, but Tag tagToAdd = Tag.findByTag(t) has already associated the instance with the session, and you are assigning to another variable. You now have two instances associated with the session, both representing the same row in the database, qt and tagToAdd (they have the same id). This produces an ambiguous situation, and is not allowed, hence the error.

It appears that you don't actually need qt to be instantiated (you only take action if it doesn't exist). So, I'd suggest doing a query to find out if it exists (perhaps a 'select count') instead of actually retrieving the object instance. That way, you'll only have one copy of the object.

like image 77
GreyBeardedGeek Avatar answered Oct 10 '22 02:10

GreyBeardedGeek