繁体   English   中英

如何在没有 JPA 的情况下实现持久锁?

[英]How to implement persistence lock without JPA?

我正在开发一个 Java Spring-Boot API 项目,该项目的数据库层不会对大多数实体使用 JPA(由于所选的数据库设计,我无法在 JPA 中实现:[数据库模型]几天前我提出了另一个问题: [问题] )。

我担心实体的并发编辑,并想知道我应该如何实施某种锁定,以避免并发更改,但不指望 JPA。

人们在 JPA 和 Hibernate 之前用来实现的一些常见方法是什么?

对于悲观锁定,JPA 最终归结为使用 JDBC 发出select * from foo where id = 1 for update (在 MySQL 情况下)锁定 ID 1 的行。 在锁定该行的事务完成之前,没有人可以选择该行(另请参阅this which select for update在某些情况下可能锁定整个表)。 所以你可以确保只有一个人可以改变这一行。

对于乐观锁定,JPA 最终归结为首先为每条记录引入一个版本号。 Whenever a record is selected , it will also select this version number (assume the selected version is 10) . 并且每当进行更新时,它总是将此版本增加一个,并使用以下AND条件检查该版本是否仍未被其他版本更改:

update foo set bar = xxxx , version = version + 1 where id = 1 and version = 10;

所以,如果没有记录可以更新,那意味着在你更新它之前另一个人已经改变了这个记录(即那个人已经将版本更新到 11,这使得你的AND条件失败)。 您可以简单地向用户显示一些错误消息,并根据您的业务需求告诉他们重新加载/重试等。

我的意思是你可以简单地使用 JDBC 模拟上述方法,因为它们最后只是一些简单的 SQL 语句......

为简单起见,请使用可序列化事务锁定。 它比类似版本的锁定更容易并解决了大部分问题。

START TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- do stuff
COMMIT;

Spring Framework 通过提供@Transactional注释使您变得容易,您可以在其中指定隔离级别以及传播策略。 我发现它非常有用且易于使用。

编辑:MySQL Aurora (AWS RDS) 不支持可序列化事务隔离级别,因此请谨慎使用。

如果还不够,请参阅@Ken Chan 的回答。 根据您的问题,您关注的是concurrent edit of the entities ,所以这应该可以解决问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM