在 Web 组件中使用 JPA 锁

Posted

技术标签:

【中文标题】在 Web 组件中使用 JPA 锁【英文标题】:Use JPA locks in web components 【发布时间】:2016-12-05 09:06:01 【问题描述】:

我了解 JPA 锁的原理(乐观和悲观),但注意到您应用于实体管理器、查询等的所有锁始终位于服务器端。所有 EJB 都位于服务器上,因此它们使用的事务也被锁定在服务器上。

假设您的电子商务网站的客户想要更改他的数据。用户在客户端(例如facelets)中填写他的更改,然后通过将它们发送到服务器来提交它们,然后服务器获得锁。但是,如果管理员在初始读取和获得锁定之前更改了客户数据怎么办?这会导致脏读

那么如何将锁定机制扩展到 Web 层? 我没有在网上找到一个选项,但是如果没有它,当前 JPA 的锁定 API 将毫无用处,不是吗?

【问题讨论】:

【参考方案1】:

为了避免脏读,但不阻塞实体,可以利用 JPA 的一个称为“版本锁定”的功能,即使用其@Version 向实体类添加一个属性。

简单示例:

@Entity
public class Persona implements Serializable 
  //... other properties

  @Version
  @Column(name="VERSION")
  private long version;

// getters and setters

现在,如果有人在您之前更新数据,然后尝试更新数据,JPA 引擎会抛出异常,指示其他人并更新信息。此选项可防止可能导致整个应用程序性能不佳的阻塞

【讨论】:

谢谢,但我熟悉乐观锁的概念。问题是 JPA 在每个事务结束时检查更改。好吧,这可以防止脏读,但仅限于事务期间。如果客户端在其浏览器中更改数据,则不存在这种安全性,因为没有确保其他人同时更改同一位数据的事务。

以上是关于在 Web 组件中使用 JPA 锁的主要内容,如果未能解决你的问题,请参考以下文章

Sprinboot中使用JPA及简单的原生分页组件

springboot分析——与其他组件的整合(JPA规范/atomikos/redis)

Java显式锁学习总结之二:使用AbstractQueuedSynchronizer构建同步组件

一篇搞定spring Jpa操作数据库

Go语言无锁队列组件的实现 (chan/interface/select)

乐观锁定的重试机制(spring data + JPA)