Spring boot REST 应用程序中的乐观锁定

问题描述 投票:0回答:1

我阅读了大量有关 Spring Boot 中乐观锁定的文档,但我无法让它适用于我的用例。我有 2 个用户在网页上提取相同版本的记录,user1 更新记录,然后 user2 更新它。所以user2的更改已经覆盖了user1所做的更改。文档讨论了使用 @Version 注释,但这不适用于我的用例,因为 Spring JPA 没有旧版本号。

我通过在 GET 请求上向客户端发送最后更新的日期时间来解决这个问题。客户端将其用作表单上的隐藏字段,并通过 PUT 请求将其发送回服务器。我现在对实体执行 findById,并将客户端发送的上次更新日期时间与 findById 方法返回的值进行比较。如果它们不匹配,我会抛出异常。

我根本没有使用@Version注释,因为它对我没有帮助。 另外,我无法更改数据库模型。我们在所有数据库表中都有一个最后更新的日期时间字段。我正在使用此字段来跟踪版本。

我还在更新之前使用 LockModeType.PESSIMISTIC_WRITE 独占锁定了记录。我无法将 LockModeType 参数传递给 JPA 存储库中的标准 findBy 方法。我需要向它传递一个参数,因为我只在更新之前需要锁定。我尝试按照下面链接中的步骤操作,并为锁定方法创建自定义存储库实现,但我不断收到无法识别 lockById 方法的错误。 https://vladmihalcea.com/spring-data-jpa-locking/

以下内容将不胜感激。

a.如果你们中的任何人都使用乐观锁定来处理与我完全相同的用例,那么您是否像我一样使用隐藏字段?如果您采用不同的方式,请告诉我。

b.如果您知道如何将 LockModeType 参数传递给标准 JPA 存储库 findBy 方法,请告诉我。如果无法完成并且我必须使用 EntityManager,那么我会尝试找到一种方法来做到这一点。

spring-boot spring-data-jpa optimistic-locking
1个回答
0
投票

当然,这很简单,因为 Spring 支持

Timestamp
作为版本字段。 注解接口版本.

@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DatabaseRecord {
    @Id
    private Long id;
    @Version
    private Timestamp lastUpdated;
    private String somethingToUpdate;
}

然后捕获异常并重试。

Optional<DatabaseRecord> databaseRecord1 = playService.query();
Optional<DatabaseRecord> databaseRecord2 = playService.query();
playService.update(databaseRecord1.get(), "first update");
try {
    playService.update(databaseRecord2.get(), "second update");
} catch (ObjectOptimisticLockingFailureException lockingFailureException ) {
    databaseRecord2 = playService.query();
    playService.update(databaseRecord2.get(), "second update");
}
System.out.println(playService.query().get());

给我

Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: update database_record set last_updated=?,something_to_update=? where id=? and last_updated=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
Hibernate: update database_record set last_updated=?,something_to_update=? where id=? and last_updated=?
Hibernate: select d1_0.id,d1_0.last_updated,d1_0.something_to_update from database_record d1_0 where d1_0.id=?
DatabaseRecord(id=1, lastUpdated=2024-01-01 14:27:02.036552, somethingToUpdate=second update)
© www.soinside.com 2019 - 2024. All rights reserved.