Java org.hibernate.transientObject在Criteria.list()期间发生异常
我在互联网上看到过关于如何在保存/更新/删除期间修复TransientObjectExceptions的帖子,但我在调用我的条件列表时遇到了这个问题 我有两个对象A和B。A有一个名为B的字段,类型为B。在我的映射中,B被映射为多对一。这一切都在一个更大的持久性框架中运行(该框架有点像核心数据),因此我在hibernate映射中不使用任何级联,因为级联是在更高的级别上处理的 这是围绕我的标准的有趣代码:Java org.hibernate.transientObject在Criteria.list()期间发生异常,java,hibernate,Java,Hibernate,我在互联网上看到过关于如何在保存/更新/删除期间修复TransientObjectExceptions的帖子,但我在调用我的条件列表时遇到了这个问题 我有两个对象A和B。A有一个名为B的字段,类型为B。在我的映射中,B被映射为多对一。这一切都在一个更大的持久性框架中运行(该框架有点像核心数据),因此我在hibernate映射中不使用任何级联,因为级联是在更高的级别上处理的 这是围绕我的标准的有趣代码: A a = new A(); B b = new B(); a.setB(b); sessi
A a = new A();
B b = new B();
a.setB(b);
session.save("B", b); // Actually handled by the higher level
session.save("A", a); // framework, this is just for clarity
// transaction committed and session closed
...
// new session opened
Criteria criteria = session.createCriteria(A.class);
criteria.add(Restrictions.eq("b", b));
List<?> objects = criteria.list();
以下是我的映射:
有人能帮我弄清楚为什么在提取过程中会出现TransientObject异常吗?最好我想找到一个不依赖级联的解决方案,因为级联往往会掩盖在更高级别框架中出现的问题。问题是,
b
在另一个会话中保持不变,该会话关闭,查询在新会话中创建。当会话关闭时,其持久性上下文中的所有对象都将分离。如果以后要在另一个会话中重用它们,则需要首先将它们重新连接到该会话:
session.update(b);
引自Hibernate书籍:
update()
操作
在会话上,将分离的对象重新附加到持久性上下文并
计划一个SQL UDPATE
。Hibernate必须假定客户端修改了
对象,而它是分离的。(否则,如果您确定它没有被修改,
一个lock()
就足够了。)持久性上下文将自动刷新
当会话中的第二个事务提交时,以及
对曾经分离的对象和现在的持久对象的修改是同步的
用数据库
实际上,saveOrUpdate()
方法比update()
更有用,
save()
或lock()
:在复杂的对话中,您不知道项目是否在
分离状态,或者是新的、暂时的,必须保存。自动
saveOrUpdate()
提供的状态检测在您
不仅可以处理单个实例,还可以重新连接或持久化网络
对连接的对象进行排序,并应用级联选项
请注意,还有一个
merge()
方法,用于在重新附加旧的分离实例之前将同一实体加载到新的持久性上下文中的情况。在这种情况下,您有两个物理上不同的实例代表同一个实体,因此应该将它们合并以避免出现ununiqueObjectException
另一个简单的方法是在父类映射中的子类集合映射上使用属性cascade=all。下面是映射的外观
<class entity-name="A" lazy="false">
<tuplizer entity-mode="dynamic-map" class="MyTuplizer" />
<id type="long" column="id">
<generator class="native" />
</id>
<many-to-one name="b" entity-name="B" column="b_id" lazy="false" cascade="all" />
</class>
<class entity-name="B" lazy="false">
<tuplizer entity-mode="dynamic-map" class="MyTuplizer" />
<id type="long" column="id">
<generator class="native" />
</id>
</class>
因为您在hibernate中插入了数据,例如persist()、save()。但是上面的错误是您刚刚使用了执行更新信息的do merge()和others方法。能否显示对象b
在代码中的来源?是坚持吗?彼得你是个天才!我保存b的会话到此点已经结束很久了,因此我必须在新会话中更新b,然后再根据条件调用列表。请添加一个答案,这样我就可以奖励你。谢谢:-)我同时添加了我的答案。再次感谢彼得!在你指出这一点之前的几天里,我一直在思考这个问题。当我尝试你的解决方案时,我也遇到了同样的问题:}:org.springframework.dao.DuplicateKeyException:具有相同标识符值的不同对象已经与会话关联:除了我在问题中明确表示我不想要出于问题中提到的原因使用级联。我同意并尊重您在顶部的解释。但由于这个博客搜索可以在网上进行,我想提出一个不同的场景,当级联不需要代码处理时,可以这样做。也会修改我的角色。
<class entity-name="A" lazy="false">
<tuplizer entity-mode="dynamic-map" class="MyTuplizer" />
<id type="long" column="id">
<generator class="native" />
</id>
<many-to-one name="b" entity-name="B" column="b_id" lazy="false" cascade="all" />
</class>
<class entity-name="B" lazy="false">
<tuplizer entity-mode="dynamic-map" class="MyTuplizer" />
<id type="long" column="id">
<generator class="native" />
</id>
</class>