【问题标题】:Spring JpaRepostory delete vs deleteInBatchSpring JpaRepostory 删除与 deleteInBatch
【发布时间】:2014-11-26 08:18:59
【问题描述】:

Spring JpaRepostory 中的delete(...)deleteInBatch(...) 方法有什么区别?第二个“删除一条 SQL 语句中的项目”,但从应用程序/数据库的角度来看,这是什么意思?为什么存在两种结果相似的不同方法,什么时候最好使用一种或另一种?

编辑: 这同样适用于deleteAll()deleteAllInBatch() ...

【问题讨论】:

    标签: java spring spring-data


    【解决方案1】:

    只是添加一些有趣的信息。

    您不能在方法名称上使用'batch'创建自定义删除并等待spring数据解决它,例如,您不能这样做:

      void deleteByYourAttributeInBatch(Iterable<YourObject> object);
    

    你需要这样做吗:

      @Modifying
      @Transactional
      @Query("DELETE FROM YourObject qr WHERE o.yourAtribute IN (:object)")
      void deleteByYourAttributeInBatch(Iterable<YourObject> o);
    

    也许这是 spring-data 的问题 ;)

    【讨论】:

      【解决方案2】:

      这里的答案并不完整!

      首先,让我们检查一下the documentation

      void deleteInBatch(Iterable<T> entities)
      Deletes the given entities in a batch which means it will create a single Query.
      

      因此“delete[All]InBatch”方法将使用 JPA 批量删除,例如“DELETE FROM table [WHERE ...]”。这可能更有效,但有一些警告:

      • 这不会调用您可能拥有的任何 JPA/Hibernate 生命周期挂钩 (@PreDelete)
      • 它不会级联到其他实体
      • 您必须清除您的持久性上下文或只是假设它已失效。

      这是因为 JPA 会向数据库发出批量 DELETE 语句,绕过缓存等,因此无法知道哪些实体受到影响。

      See Hibernate Docs

      The actual codein Spring Data JPA

      虽然我在这里找不到具体的文章,但我会推荐 Vlad Mihalcea 所写的所有内容,以便更深入地了解 JPA。

      TLDR:“inBatch”方法使用批量 DELETE 语句,这可以大大加快速度,但有一些注意事项。他们绕过了 JPA 缓存。您应该真正了解它们的工作原理以及何时使用它们来获益。

      【讨论】:

        【解决方案3】:

        deleteInBatch(...) 在日志中看起来像这样: DELETE FROM table_name WHERE (((((((? = id) OR (? = id)) OR (? = id)) OR (? = id)) OR (? = id)) OR (? = id)) OR (? = id))

        如果有大量数据要删除,达到 SQL 服务器查询的最大大小,这可能会导致问题: Maximum size for a SQL Server Query? IN clause? Is there a Better Approach

        【讨论】:

        • 已确认,大型 deleteInBatch 调用会导致 StackOverflowError。为避免这种情况,应编写自定义查询以使用 IN 语句,或者将批处理分成更小的块。
        【解决方案4】:

        delete 方法将在一次操作中删除您的实体。 deleteInBatch 将批量处理多个删除语句并将它们作为 1 个操作删除。

        如果您需要大量删除操作,批量删除可能会更快。

        【讨论】:

        • 好的,我明白了。但它仍然没有回答为什么存在两种方法?如今,每个人都希望越来越快地执行所有操作,所以为什么不使用例如。 deleteAllInBatch 实现作为 deleteAll 的默认实现并 KISS 整个 JPARepository API。
        • 因为批处理会对性能产生影响。它只比来自一定数量操作的单个查询快。
        • delete删除一项,deleteAll删除所有项,一项一项(它调用“从 where id=?”中删除N次),deleteInBatch通过单个sql删除操作删除所有项:“从
          中删除”。如果我们将它与 delete() 或 deleteAll() 进行比较,我相信这对 deleteInBatch 没有性能影响
        • 如果你的实体包含 @ElementCollection 你应该使用 deleteAll() 而不是 deleteAllInBatch()
        • 这不是一个完整的答案。它非常简化,甚至不提供文档。我还没有对此进行研究,但我敢打赌,使用批处理方法会跳过很多事情,比如应用程序提供的实体侦听器和持久性提供者的验证逻辑。
        猜你喜欢
        • 2015-06-21
        • 1970-01-01
        • 2011-05-14
        • 2021-09-06
        • 2021-06-17
        • 1970-01-01
        相关资源
        最近更新 更多