【问题标题】:Best practice for when to start a new session/transaction for batch jobs using spring/hibernate and when to commit/flush the session?何时使用 spring/hibernate 为批处理作业启动新会话/事务以及何时提交/刷新会话的最佳实践?
【发布时间】:2011-06-22 03:22:48
【问题描述】:

我在 spring 中设置了一个 tx-advice 来围绕我的 Service 方法包装一个事务。所以说在我的批处理类中,我调用一个服务方法来加载对象列表并将其返回给我的批处理类。然后在我的批处理类中,我调用一个服务方法来处理每个对象。但是,如果该服务方法尝试访问对象的延迟加载属性,我将收到延迟加载异常,因为该对象列表是使用不同的休眠会话加载的。

因此,一种可能不是最佳的解决方法是 - 批处理类只是调用一个服务来加载这些对象的所有 ID(长值) - 我们将此 ID 传递给一个服务方法,该方法将加载它通过 ID 从数据库中获取对象,然后对其进行处理。

对此有什么想法?

我遇到的另一个问题是,如果这些对象中的每一个都相互独立,我应该还是不应该一次保存每个对象,而不是一次保存所有对象或批量保存它们。如果有 5000 条记录,那么在调用保存/更新/插入时应用程序似乎会减慢很多,因为它仍在 Hibernate 会话中的内存中执行所有这些操作。但是,如果我改为保存/更新/插入每条记录(一次处理一个 ID),然后在使用该对象完成后提交,然后再转到下一个,它似乎加快了很多。此外,如果我批量处理它,比如每 200 条甚至一次全部 5000 条,如果一条记录无法插入/更新并出现错误,则不会保留任何内容并且一切都会回滚。

处理此类事情的最佳做法是什么?似乎真的很常见。谢谢

【问题讨论】:

    标签: java hibernate spring session transactions


    【解决方案1】:

    首先,Spring/Hibernate 并不是真正用于批处理。相反,请查看TalendPentaho(如果您喜欢开源),或任何大量(大量!)各种商业工具。这些工具中的任何一个都可用于自动生成一组 Java 代码,这些代码将完全满足您的需求(包括插入优化、优雅的错误处理等)。

    好吧,让我们假设您真的非常想让 Spring/Hibernate 进行批处理。您有几个不同的问题 - 首先,Hibernate 会话生命周期意味着加载的对象期望与实时会话相关联。您可以使用会话 flush() 强制更改传播到数据库。会话 close() 将清除所有内容。已经加载的对象只能重新附加到一个新的会话有困难(通常重新加载对象更容易)。如果您不关闭()/刷新()您的会话,最终您将(可能)耗尽内存。您可以通过添加 Hibernate 二级缓存来解决这个问题……但这只会让事情变得更加复杂并减慢速度。

    没有真正的理由不在独立的 Hibernate 会话(打开、工作、关闭)中进行每次插入。它不会像专用工具那样快,但它很简单,可以正常工作,并且或多或少与您将获得的一样好。

    【讨论】:

      【解决方案2】:

      关于批处理要求,请使用Spring批处理link 这提供了所需的所有必要的批处理设施。

      关于对象加载问题,

      所以解决这个问题的方法可能不是 最优化的是 - 批处理类 只需调用一个服务来加载所有 这些对象的 ID(长值) - 我们将这个 ID 传递给服务 将加载该对象的方法 通过 ID 从数据库中获取,然后执行 处理它。

      似乎是正确的。

      【讨论】:

        猜你喜欢
        • 2011-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-18
        • 1970-01-01
        • 2013-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多