【问题标题】:What is the best way to update row using spring data with best performance value? [closed]使用具有最佳性能值的弹簧数据更新行的最佳方法是什么? [关闭]
【发布时间】:2019-03-30 13:42:51
【问题描述】:

我正在使用弹簧数据。现在我的任务是在应用程序的性能和数据一致性非常关键的部分更新实体。实体中有 isLocked 字段。许多事务和业务逻辑都在这个领域中继。我希望能够以最有效和最安全的方式更新此字段。

我看到了两种方式:

  1. 使用@Query 和 jpql 更新语句。这种方法有利于只对 db 执行一个请求。但我不确定交易安全。

  2. 在 java 中使用 findById@Lock(LockModeType.PESSIMISTIC_WRITE) 并修改字段。这种方法的缺点是至少向 db 发出 2 个请求,但由于锁定,跨国安全。

你会推荐什么?也许有不同的最合适的方法我不知道。

【问题讨论】:

  • 您只是在使用普通交易吗? @Transactional 几乎总是足够的(尽管如果由于某些令人惊讶的原因您手头没有对象,那么直接执行更新就不需要先获取它)。
  • 我使用@Transactional。我想知道为什么有这么多在 java 端更新的例子。使用@Query 更新更有效,不是吗?
  • 它更效率,但是您必须编写查询并显式执行它们,而 JPA 的重点是您可以使用 POJO 编写普通的 Java 代码,而不必担心数据库细节。
  • 所以 jpql 数据库也是不可知的。

标签: java spring jpa spring-data-jpa spring-data


【解决方案1】:

如果您询问有效性,这两个选项都非常有效。因此,您的选择归结为非功能性需求。

您在问题中提到了表现;使用 Query 的选项肯定会更高效。不仅因为它最终会执行一次数据库调用而不是两次(如果你玩得聪明并且有多个要更新,你甚至可能一次调用一大堆记录而逃脱),还因为检索一个实体修改它涉及到水合它并将其添加到实体管理器会话中,与简单的查询相比,这相当昂贵。也就是说,作为一般原则,您应该仅在性能成为问题时根据性能做出决定(谷歌“过早优化”以获得更多信息)。

要考虑的另一个方面是稳健性。通常,实体不仅仅是一个愚蠢的数据存储。它包含逻辑和业务规则,并且肯定会有验证存在于您的代码库中,但不存在于您的数据库中。使用 Query 可以绕过所有这些,并迫使您在两个位置对这些业务规则进行编码;一次在您的域中,一次在您的查询中。即使现在您正在更新的字段是“愚蠢的”,假设它不会保持这种状态也不错。

第三是可维护性。整个想法,像 JPA 这样的东西存在的原因,是因为“从存储库中获取项目,更改字段,并保存更改(或提交事务)”是这么简单的事情。出错的可能性较小,任何人都可以阅读和推理。如果您不打算使用它,为什么要首先使用 JPA?

【讨论】:

    【解决方案2】:

    Spring Data Jpa 可以处理版本化实体。只有当对象和数据库中的版本属性相同时,当前线程才能更新实体。

    只需将以下属性添加到您的实体,其余的由 Spring Data Jpa 完成:

     @Version
     private Long version;
    

    当您调用repository.save(entity) 方法时,它使用以下子句扩展UPDATE 查询:... and version=?。 并且它还会在保存前自动增加版本。

    【讨论】:

    • 但是我的效果不如@Query("Update entity where id =?1")
    • 查询将是:Update entity set version=25 where id=1 and version = 24。如果更新不成功,则会出现异常。而且它不需要锁定。
    • 但在此之前我必须阅读实体。这是对 db 的 +1 请求。
    • 好吧,如果你想更新实体,无论如何你都需要了解它。如果要增加或减少属性,则需要原始值。如果您只是想覆盖一个属性而不考虑先前的值,那么您无论如何都不需要锁定。也许您应该分享实际用例。
    猜你喜欢
    • 2010-09-09
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2014-11-03
    • 2013-08-10
    • 2021-10-23
    相关资源
    最近更新 更多