【问题标题】:Hibernate JPA DB closing connection when persisting many entities持久化许多实体时休眠 JPA DB 关闭连接
【发布时间】:2021-09-09 17:26:55
【问题描述】:

我有一个大约 20 000 个实体的列表,这些实体是循环的,并使用这样的 persists 方法添加到 EntityManager:¨

public final void createE(e entity) {
    em.persist(entity);
}

那么这里有什么问题呢?为什么连接会关闭? Hibernate 不应该处理这个问题并在需要时建立一个新的连接吗?

【问题讨论】:

  • 什么是处理事务范围? Persist 本身是一个将对象注册到 EntityManager 上下文中的无操作,但在事务提交之前它不会插入 - 正是该事务对您超时。您必须管理大小和连接属性,以便事务可以在您的驱动程序/系统配置为允许其保持打开状态的时间内完成。
  • 嗯好的,但是当我去远程数据库而不是本地时,为什么这个循环需要 1 小时?实体管理器是否自己决定何时将其实际写入数据库?
  • 不,它没有,事务范围有。可能不是需要花费一小时的循环,而是事务提交时的事务调用(提交/刷新)应该会导致您使用已配置的 JDBC/数据源将持久化的所有内容写入数据库。您将需要查看从数据库到应用程序的所有设置,以针对此用例对其进行调整,并可能将您的事务分解为更小的块(如果您在 20k 单独的事务中这样做,则可能更大)以便它们能够成功在合理的时间内,甚至异步运行。

标签: java hibernate jpa


【解决方案1】:

您是否配置了批量大小?

例如:

hibernate.jdbc.batch_size 200

https://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/batch.html

【讨论】:

  • 我确实有一个配置文件 persistence.xml 将批量大小设置为 25。
  • 好的,然后尝试为 SQL 启用日志,看看发生了什么。 SQL 批处理,或直接在数据库上导出和重新加载可能是另一个不错的选择。
  • 现在我已经将批处理选项设置为 50。以这种配置方式,恐怕我无法获得任何 SQL 日志。
  • 它是如何配置的,你在本地没有属性文件,或者没有办法将 sql 记录到代码中?
【解决方案2】:

Hibernate 不应该处理这个问题并在需要时建立一个新连接吗?

不,这不是交易的运作方式。作为开发人员,您可以做的是为每个例如创建和提交事务。 1000 个实体或任何适合您的批次/块大小。请注意,连接关闭可能是因为您的计算机和服务器之间的网络不可靠,而 localhost 连接显然是完全可靠的。由于带宽限制或更高的延迟,甚至可能仅仅是因为数据库服务器正忙于执行其他 IO,因此需要更长的时间。

【讨论】:

  • 我试过了,我将列表分成单独的列表,每个列表包含 1000 个元素。这确实有效,但仍需要 1 小时才能完成,而不是像在 localhost 上那样需要 3 分钟。我认为它不是需要时间的实际数据库交互,而是在事务中持久化对象。 5 列整数数据的 20 000 行并不是特别重的负载,任何现代数据库都应该能够轻松处理。此外,我在 1 gbit 上下光纤上,应该没问题。 db 上的负载也很低,查看统计数据时使用率不到 1%。
  • 我不知道你的意思是什么类型的负载,但是写入磁盘是 IO 绑定的,即使你有一个 1 gbit 的网络,这并不意味着数据库可以写得这么快。您必须检查一些事情才能了解瓶颈在哪里,但通常是磁盘或网络 IO 导致速度变慢。另一个可能的问题是提交后您没有清除实体管理器的持久性上下文。在提交之前总是做em.flush(); em.clear();
  • 是的,但是当它循环并被持久化时什么都没有写入,它只在一切完成后才写入数据库,并且该操作只需要一秒钟。它是需要时间的实体管理器。如果是磁盘 IO,我会在监控中看到它。当然它可以是网络,但我猜 Azure 数据中心应该是合理的快。据我了解,该代码根本不做任何提交、刷新或清除,我只有我发布的代码。这段代码大约有 15 年的历史,而且它的意大利面到处都是,所以我更喜欢尽可能少地修改。
  • 如果您想要更好的性能,您可能必须更改代码,问题的一个可能来源是事务大小,因此您可能应该对每个块进行提交。请参阅此答案以了解其外观:stackoverflow.com/questions/67619692/…
  • 谢谢,是的,我确实尝试过(但没有使用刷新或清除),但第一个元素和最后一个元素一样慢,我担心它根本不会改变执行时间。此外,实施起来会非常混乱,因为使用 em 的类不接受项目列表,当时只有一个实体。因此,我将不得不更改类使用的接口以及使用空方法的接口的所有类..不理想。
猜你喜欢
  • 1970-01-01
  • 2019-12-08
  • 2012-01-09
  • 2020-02-14
  • 2018-09-09
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
相关资源
最近更新 更多