java - Web应用程序中的并发控制

标签 java spring spring-mvc jpa concurrency

我必须解决这种情况:在我的 Spring + JPA web 应用程序中,我有一个类似于 excel 工作表的 jsp。

所以我有一定数量的单元格,每个单元格都保存在一个带有附加信息的数据库表中:每个单元格都有一行。

id | value | column | row | ...

我使用这种结构是因为我的 jsp 表中的列数是动态的。

目前,当我保存单元格时,我会截断数据库表中的当前行集并重新插入所有新行。这是我发现更新大量行的最快方法。

但是现在我有一个并发问题:jsp页面可以同时被不同的用户使用,这会导致覆盖其他用户节省的问题

我需要在我的网络应用程序中实现某种锁定。我发现主要有两种类型的锁:乐观锁和悲观锁。

您能建议我解决这种情况的通用方法吗?我需要在哪里实现锁定,是在数据访问级别还是在服务级别?

注意更清楚:表值在用户之间共享,但授权用户中的任何人都可以更新。

最佳答案

解决方案可能取决于行为要求。

以下场景如何:用户 A 和 B 开始更改一些值,然后用户 A 按下保存按钮并保存数据,之后用户 B 也这样做。用户 B 收到类似“数据已更新,请重新加载页面”之类的错误消息。他重新加载页面并丢失他所做的所有更改 :( 只有在那之后他才能保存他的更改,但他必须再次执行此操作。

其他可能的情况:用户 A 和 B 访问该页面,但只有第一个用户可以保存他的工作,其他用户会看到类似“其他人正在编辑页面,稍后再试”的消息".

对于第一种情况,您可以执行以下操作:表(在数据库中)的每一行都有一个上次更新时间戳,每次更改该行时都会更新为当前时间。 现在,假设用户 A 在打开页面时获取了时间戳为 1 的行,而用户 B 稍慢一点,并获取了时间戳为 2 的同一行。但是,他更快地进行了更改,并先按下了“保存”按钮。现在,该行保存在数据库中,并带有时间戳,比方说 5。用户 A 试图保存他的更改,但他的数据的时间戳是 1,这与当前在数据库中的 5 不同。这意味着有人已经更改了该数据,他应该会看到我上面提到的错误消息。

第二种情况有点难以实现。我认为最好的方法是向 DB 打开事务

  • 读取我们想要的行;
  • 为所有这些设置一些标志,如“locked”为 true
  • 如果某些行已经被锁定,则失败(或返回可用行,具体取决于您的需要)。但是,可能应该失败;
  • 将行返回到 jsp 页面;

现在,如果其他用户请求相同的行,事务将失败并且他将无法开始更改数据。

用户 A 在保存数据时应将这些 locked 标志恢复为 false重要事项:这些锁应该有超时,以防止用户打开页面并在没有保存的情况下关闭页面(或浏览器崩溃,或其他原因)。您可能还想为同一用户实现某种锁定重新确认 - 当用户第一次打开页面,然后在不保存数据的情况下关闭页面并再次打开时 - 他应该能够编辑数据。这可以通过以某种方式识别用户 - 登录名、cookie 等来完成。

关于java - Web应用程序中的并发控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26677044/

相关文章:

spring-mvc - 仅发送到某些连接Spring Websockets

java - (java) 如何测试输入值是否为 int 类型?

java - 安卓+Java :File deletion error

java - Spring Boot Junit测试通过构造函数注入(inject)注入(inject)dao接口(interface)

java - Spring RestTemplate - 异步与同步 restTemplate

java - Spring 和 thymeleaf 以 html 作为资源

java - 如何在 thymeleaf 中打印数组大小?

Spring MVC : how can I re-load the logged-in user information from the database on each Thymeleaf page?

java - 使用 ClassTag 获取包含泛型类型

Spring+JPA+DAO+Tomcat