可能重复:
Hibernate: different object with the same identifier value was already associated with the session
我在Grails中的控制器中有以下代码,但出现"a different object with the same identifier value was already associated with the session"
错误消息失败。
我已经访问了几个页面,其中说我必须在调用save之前调用"merge"
,最后会出现此错误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)
}
}
----------- --------------- 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)
}
}
答案 0 :(得分:3)
由于您执行了Quiz.get(id)
,因此您已经连接了'例如,所以你绝对不需要合并' - 仅用于重新连接断开连接的实例。
我认为您收到错误的原因是该行:
def qt = QuizTag.findByQuizAndTag(q, tagToAdd)
将QuizTag
实例拉入会话,但Tag tagToAdd = Tag.findByTag(t)
已将实例与会话相关联,并且您要分配给另一个变量。您现在有两个与会话关联的实例,它们都代表数据库中的同一行qt
和tagToAdd
(它们具有相同的ID)。这会产生不明确的情况,因此不允许出现错误。
您似乎实际上并不需要qt
进行实例化(如果它不存在,您只会采取行动)。因此,我建议您查询是否存在(可能是' select count
'),而不是实际检索对象实例。这样,您只能拥有该对象的一个副本。
答案 1 :(得分: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)
}