Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate “圣杯”;具有相同标识符值的不同对象已与会话关联;错误_Hibernate_Grails_Groovy_Grails Searchable - Fatal编程技术网

Hibernate “圣杯”;具有相同标识符值的不同对象已与会话关联;错误

Hibernate “圣杯”;具有相同标识符值的不同对象已与会话关联;错误,hibernate,grails,groovy,grails-searchable,Hibernate,Grails,Groovy,Grails Searchable,可能重复: 我在Grails中的控制器中有以下代码失败,原因是“具有相同标识符值的不同对象已与会话关联”错误消息。 我已经访问了一些页面,其中说明我必须在调用save之前调用“merge”,最终导致为com.easytha.QuizTag类提供的id类型错误。预期:类java.lang.Long,获得类org.hibernate.action.DelayedPostInsertIdentifier 有人建议grails searchable插件可能是造成这种情况的原因,我应该从我的域类中删除s

可能重复:

我在Grails中的控制器中有以下代码失败,原因是
“具有相同标识符值的不同对象已与会话关联”
错误消息。 我已经访问了一些页面,其中说明我必须在调用save之前调用
“merge”
,最终导致
为com.easytha.QuizTag类提供的id类型错误。预期:类java.lang.Long,获得类org.hibernate.action.DelayedPostInsertIdentifier

有人建议grails searchable插件可能是造成这种情况的原因,我应该从我的域类中删除searchable=true,这不是一个选项(请参阅前面的文章)

需要指出的一点是,在调用q.save()时不会抛出错误,而是在调用重定向重定向时抛出错误(操作:“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)
        }
    }
-----------编辑---------------


由于您进行了
quick.get(id)
,因此您有一个“已连接”实例,因此您肯定不需要“合并”-这只是为了重新连接一个已断开连接的实例

我认为您出现错误的原因是:

def qt = QuizTag.findByQuizAndTag(q, tagToAdd)
QuizTag
实例拉入会话,但
Tag tagToAdd=Tag。findByTag(t)
已将该实例与会话关联,您正在分配给另一个变量。现在有两个与会话关联的实例,它们都表示数据库中的同一行,
qt
tagToAdd
(它们具有相同的id)。这会产生不明确的情况,并且是不允许的,因此会出现错误


看起来您实际上不需要实例化
qt
(只有在它不存在的情况下才采取行动)。因此,我建议执行查询以确定它是否存在(可能是“
select count
”),而不是实际检索对象实例。这样,您将只有对象的一个副本。

默认情况下,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)
}

从save()方法的描述中可以看出:“除非使用flush参数,否则对象不会立即持久化。”这就是为什么只有在请求完成时才会发生错误。@TiagoFarias您是对的。在调用q.save(flush:true)之后,我在那一行得到了正确的错误,这里要注意的另一件事是,即使在错误发生之后,我的数据仍然被保存!此外,只有当标记已经存在,即“tag.findByTag(t)”根据您的建议返回某些内容时,才会发生此错误。“编辑”中的新代码不应该工作吗?对不起,我不理解您的问题。什么是“编辑中的新代码”?:)我是指原始帖子中的编辑区域。其中,我将变量赋值更改为Tag tagToAdd=Tag.findByTag(t)∶new Tag(Tag:t)和def qt=QuizTag.findByQuizAndTag(q,tagToAdd)∶new QuizTag(quick:q,Tag:tagToAdd);你不认为那会奏效吗!不,我不这么认为。你需要把事情安排好,这样你就不会在同一个会话中两次实例化同一个对象。嘿,我在我的原始帖子中的--EDIT--中再次更新了我的代码,但我仍然得到相同的错误!!有什么提示吗?好吧,我上面的代码工作了,但现在它没有索引标签和测验!!所以没有搜索结果:)行为看起来很随机,它刚刚开始工作,但现在调用q.save时出现了相同的错误(flush:true)
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)
}