【问题标题】:"Detached entity passed to persist" despite flush()尽管有flush(),但“分离的实体传递给坚持”
【发布时间】:2021-05-06 10:18:54
【问题描述】:

我有一段长时间运行的 JPA+Hibernate 代码,它试图循环插入大量记录到数据库中。

随着时间的推移(可能是因为 EntityManager 缓存建立/脏检查),处理速度变得越来越慢。为了解决这个问题,我决定在每次迭代结束时使用em.flush()em.detach(entity),因为一旦实体被持久化,我就不需要它的数据进行进一步处理(不幸的是我不能使用em.clear() 或批处理,为了减少我的更改的外部影响)。

这是我的代码的粗略草稿:

for (...) {
    ...some selects here...
    ...create new entity object...
    em.persist(entity);
    em.flush();
    em.detach(entity);
}

使用此序列,对于在上一次迭代中分离的实体,我得到“分离的实体传递给持久”错误。 为什么分离前的flush() 不能防止错误?另外,如果我将detach() 替换为clear(),一切正常。 我的印象是 clear()detach() 的行为方式相同?

更奇怪的是,我可以使用以下代码在单次迭代中重现错误。 second 刷新会引发“分离实体...”错误。 这是否意味着第一次刷新是空操作?

em.flush();
em.detach(entity);
em.flush();

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    flush() 将任何更改与数据库同步,例如,如果您修改了一个对象并调用flush(),将触发更新。请注意,您通常不必显式调用它,因为刷新通常发生在事务提交时。

    如果您想减少持久性上下文中的元素数量,您需要调用clear()。这将实质上重置实体管理器

    【讨论】:

    • 两件事:如果我不刷新,我无法从持久性上下文中删除对象(使用 clear() 或 detach()),因为我会丢失更改。 JPA 文档明确说明了这一点。如果我不从持久性上下文中删除对象,它会随着时间的推移而建立。第二件事 - 为什么清除工作但不分离?它们不是都用于从持久性上下文中删除实体吗?
    • 您可能同时遇到多个问题,因为您说它在第一次迭代时失败。我在调用 detach() 时看到的问题是您只分离了一个实体,但您可能已经在 EM 中加载了其他对象。我认为每次循环迭代都有一个事务会更清楚;这将从等式中删除 flush() 和 detach()。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 2011-09-16
    • 2015-04-22
    • 2021-07-18
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多