我必须在我的项目中使用 Hibernate 4.1.7。不幸的是,我不能决定是否迁移到新版本。
在我的上下文中,我有一个主从情况。因此,我加载主对象并将其及其所有详细信息显示在网页上。我可以按照我喜欢的方式更改主控和详细信息,甚至包括新的详细信息。我的保存代码如下:
@Override
@Transactional
public void save(Entity entity) {
Session session = entityManager.unwrap(Session.class);
session.saveOrUpdate(entity);
session.flush();
}
当我尝试删除详细信息时出现问题。下面的代码显示了它是如何完成的:
myMaster.getDetails().remove(myDetail);
我希望 Hibernate 将跟踪主对象的更改(它从列表成员中丢失了详细实例),但是当我调用 save()
方法时,它会抛出 java.lang .IllegalArgumentException:正在删除分离的实例 xxxx#yyyy
。
如果尝试删除分离的实例,我理解这个概念,但我不明白为什么 Hibernate 认为刚刚删除的实例是分离的。
有什么想法吗?
TIA!
最佳答案
要使其按照您期望的方式工作(让 Hibernate 检查整个对象图),您需要做的就是:
@Override
@Transactional
public Entity save(Entity entity) {
return entityManager.merge(entity);
}
当然,请确保MERGE
操作从主控级联到详细信息(CascadeType.MERGE
或CascadeType.ALL
)并且orphanRemoval
设置为详细信息收集。如果 orphanRemoval
不合适,那么您必须显式删除详细信息(否则 Hibernate 会在关联的子级不再与父级关联时删除它们,这显然是不可取的)。
此外,请确保随后使用 merge
操作的结果,因为它始终返回传入的分离实例的副本(传入的实例不会被修改)。这在持久化新实例时尤其重要,因为 id 是在副本中设置的。
但是,您要付出从数据库重新加载对象图的代价,但是,如果您希望所有事情自动完成,Hibernate 没有其他方法来检查实际更改的内容,除了与数据库中的当前状态进行比较之外。
现在解释一下您在尝试中观察到的情况:
您保存的主实例已分离。您将其加载到一个事务(持久性上下文/ session )中,然后将其保存在另一个事务中。
它可以与
saveOrUpdate
配合使用。当你更新它时:Either save(Object) or update(Object) the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking).
Parameters:
object - a transient or detached instance containing new or updated state
如文档中所述,它旨在处理分离和 transient 实例。
您尝试合并,但出现异常,告诉您已经存在具有相同 id 的对象。唯一的解释是你尝试过这样的事情:
@Override @Transactional public void save(Entity entity) { entity = entityManager.merge(entity); Session session = entityManager.unwrap(Session.class); session.saveOrUpdate(entity); session.flush(); }
然后会抛出异常,如
update
中所述。 javadoc:Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown.
因此,您将实例合并到当前的持久性上下文中,然后尝试
saveOrUpdate
它(委托(delegate)给update
),这导致了异常,因为您当当前持久化上下文中已经存在持久化实例时,不得更新分离实例(否则持久化实例将变得过时)。您不必这样做,只需合并即可,在事务结束时,Hibernate 将脏检查对象并自动将更改刷新到数据库。
关于java - 如何让 Hibernate 4 停止抛出 "Deleting detached instance"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43279988/