我正在使用弹簧数据。现在,我的任务是在应用程序的非常重要的性能和数据一致性关键部分中更新实体。实体中有isLocked字段。许多事务和业务逻辑都依赖于此领域。我希望能够以最有效,最安全的方式更新此字段。
我看到两种方式:
使用@Query
和jpql更新语句。这种方法的好处是仅对db发出一个请求。但是我不确定交易安全性。
使用findById
和@Lock(LockModeType.PESSIMISTIC_WRITE)
并修改Java中的字段。这种方法的缺点是至少有2个对db的请求,但是由于锁定,跨国安全。
您会推荐什么?也许有另外一种我不知道的最合适的方法。
答案 0 :(得分:0)
Spring Data Jpa可以处理版本化的实体。仅当对象和数据库中的version属性相同时,当前线程才能更新实体。
只需将以下属性添加到您的实体,其余的由Spring Data Jpa完成:
@Version
private Long version;
当调用repository.save(entity)
方法时,它将使用以下子句扩展UPDATE
查询:... and version=?
。
并且还会在保存之前自动增加版本。
答案 1 :(得分:0)
如果您询问有效性,则两种选择都非常有效。因此,您的选择取决于非功能性需求。
您在问题中提到了性能;使用Query的选项肯定会更有效。不仅因为它最终将只执行一个数据库调用,而不是两个数据库调用(并且如果您玩得很聪明并且有多个数据库要更新,那么您甚至可能只用一次调用就可以获得全部记录),而且还因为检索一个实体修改它涉及将其水化并将其添加到实体管理器会话中,与简单查询相比,这是非常昂贵的。话虽如此,作为一般原则,只有在性能成为问题时才应基于性能做出决定(有关此问题的更多信息,请使用Google“过早优化”)。
要考虑的另一个方面是坚固性。通常,实体不仅仅是一个哑数据存储。它包含逻辑和业务规则,并且代码库中肯定存在验证,但数据库中肯定没有。使用Query可以避免所有这些情况,并迫使您在两个位置对这些业务规则进行编码。一次在您的域中,一次在您的查询中。即使现在您要更新的字段是“哑巴”,也可以假设这种情况不会持续下去,这并不是一件坏事。
第三是可维护性。整个想法(诸如JPA之类的东西之所以存在)是因为“从存储库中获取项目,更改字段并保存更改(或提交事务)”是如此简单的事情。错误的机会更少,任何人都可以阅读并对此进行推理。如果您不打算使用它,为什么首先要使用JPA?