Java 使用具有最佳性能值的spring数据更新行的最佳方法是什么?

Java 使用具有最佳性能值的spring数据更新行的最佳方法是什么?,java,spring,jpa,spring-data-jpa,spring-data,Java,Spring,Jpa,Spring Data Jpa,Spring Data,我使用的是spring数据。现在,我的任务是更新应用程序中非常关键的性能和数据一致性部分的实体。实体中存在isLocked字段。许多事务和业务逻辑都依赖于此字段。我希望能够以最有效和安全的方式更新此字段 我认为有两种方式: 使用@Query和jpql update语句。这种方法的优点是只向数据库执行一个请求。但我不确定交易的安全性 将findById与@Lock(LockModeType.悲观写入)一起使用,并在java中修改字段。这种方法的缺点是至少有2个对数据库的请求,但由于锁的存在,安全性

我使用的是spring数据。现在,我的任务是更新应用程序中非常关键的性能和数据一致性部分的实体。实体中存在isLocked字段。许多事务和业务逻辑都依赖于此字段。我希望能够以最有效和安全的方式更新此字段

我认为有两种方式:

  • 使用
    @Query
    和jpql update语句。这种方法的优点是只向数据库执行一个请求。但我不确定交易的安全性

  • findById
    @Lock(LockModeType.悲观写入)
    一起使用,并在java中修改字段。这种方法的缺点是至少有2个对数据库的请求,但由于锁的存在,安全性会降低


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

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

    只需将以下属性添加到实体中,Spring Data Jpa即可完成其余操作:

     @Version
     private Long version;
    
    调用
    repository.save(entity)
    方法时,它使用以下子句扩展
    UPDATE
    查询:
    。。。和版本=?

    而且它还会在保存之前自动增加版本。

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

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

    另一个需要考虑的方面是健壮性。通常,实体不仅仅是一个哑数据存储。它包含逻辑和业务规则,肯定会有验证存在于代码库中,但不会存在于数据库中。使用查询绕过了所有这些,并迫使您将这些业务规则分为两部分进行编码;一次在域中,一次在查询中。即使现在你正在更新的领域是“愚蠢的”,假设它不会保持这种状态也不是一场糟糕的赌博


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

    您只是在使用普通事务吗<代码>@Transactional几乎总是足够的(尽管如果由于某些令人惊讶的原因您手头上还没有对象,那么直接执行更新就不需要首先获取它)。我想知道为什么有这么多关于java端更新的例子。使用
    @Query
    进行更新更有效,不是吗?它更有效,但您必须编写查询并显式执行它们,而JPA的要点是,您可以使用POJO编写普通Java代码,而不必担心数据库细节。因此jpql数据库也不可知。但我的效率不如使用@Query(“更新实体,其中id=?1”)查询将是:
    updateentityset version=25,其中id=1,version=24
    。如果更新不成功,则会出现异常。并且不需要锁定。但在此之前,我必须读取entity。这是对db的+1请求。好吧,如果您想更新该实体,您仍然需要了解它。如果您想增加或减少属性您需要原始值。如果您只是想覆盖一个属性而不考虑前面的值,那么您不需要锁定。也许您应该共享实际用例。