gpt4 book ai didi

java - 如何让 Hibernate 4 停止抛出 "Deleting detached instance"?

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:04:04 25 4
gpt4 key购买 nike

我必须在我的项目中使用 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 操作是从 master 级联到 details(CascadeType.MERGECascadeType.ALL)并且 orphanRemoval 设置为收集详情。如果 orphanRemoval 不合适,那么您必须显式删除详细信息(否则 Hibernate 会在关联的子项不再与父项关联时删除它们,这显然是不可取的)。

此外,请确保之后使用 merge 操作的结果,因为它总是返回传入的分离实例的副本(传入的实例未被修改)。这在持久化新实例时尤为重要,因为在副本中设置了 id。

但是,您要付出从 db 重新加载对象图的代价,但是,如果您希望自动完成所有操作,Hibernate 除了将它与 db 中的当前状态进行比较之外,没有其他方法来检查实际发生了什么变化。

现在解释您在尝试中观察到的内容:

  1. 您保存的主实例已分离。您在一个事务(持久性上下文/ session )中加载它,然后将其保存在另一个事务中。

  2. 它与 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 实例一起使用。

  3. 您尝试合并,但出现异常,告诉您已经有一个具有相同 ID 的对象。唯一的解释是你试过这样的事情:

    @Override
    @Transactional
    public void save(Entity entity) {
    entity = entityManager.merge(entity);
    Session session = entityManager.unwrap(Session.class);
    session.saveOrUpdate(entity);
    session.flush();
    }

    然后抛出异常,如 update 中所述文档:

    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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com