Grails"具有相同标识符值的不同对象已与会话关联"错误

Sap*_*Sap 5 grails groovy hibernate grails-searchable

可能重复:
Hibernate:具有相同标识符值的不同对象已与会话关联

我在Grails中的控制器中有以下代码,但失败并显示"a different object with the same identifier value was already associated with the session"错误消息.我已经访问了几个页面,它说我必须"merge"在调用save之前调用,最后会出现此错误Provided id of the wrong type for class com.easytha.QuizTag. Expected: class java.lang.Long, got class org.hibernate.action.DelayedPostInsertIdentifier

有人建议grails searchable插件可能会导致这种情况,我应该删除searchable = true表单我的域类,这不是一个选项(请参阅上一篇文章grails searcheable plugin search in inner hasMany class)

有一点需要注意的是,在调用q.save()时不会抛出错误,而是在调用redirect redirect(action:"show",id:id)时抛出错误!

有什么建议?

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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

- - - - - -编辑 - - - - - - - -

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)
        }
    }
Run Code Online (Sandbox Code Playgroud)

sch*_*159 0

默认情况下,Grails 使用 Hibernate 代理延迟加载集合。因此,可能QuizTag正在创建重复的代理(或代理和膨胀的对象),这导致了您的问题。

你可以尝试这样的事情:

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)
}
Run Code Online (Sandbox Code Playgroud)