我必须解决这种情况:在我的 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/