我必须解决这种情况:在我的Spring + JPA Web应用程序中,我有一个类似于excel工作表的jsp。
所以我有一定数量的单元格,每个单元格都保存在DB表中,并附带有附加信息:每个单元格都有一行。
id | value | column | row | ...
我使用这种结构,因为我的jsp表中的列数是动态的。
目前,当我保存单元格时,我会截断数据库表中的当前行集并重新插入所有新行。这是我发现更新大量行的最快方法。
但是现在我遇到了并发问题: jsp页面可以被不同的用户同时使用,这可能会导致其他用户节省的覆盖问题。
我需要在我的网络应用中实现某种锁定。我发现主要有两种类型的锁:乐观与悲观。
你能建议我解决这种情况的常用方法吗?在数据访问级别或服务级别,我需要在哪里实现锁定?
注意更清楚:表值在用户之间共享,但可由授权用户中的任何人更新。
答案 0 :(得分:1)
解决方案可能取决于行为要求。
以下场景如何:用户A和B开始更改某些值,然后用户A按下保存按钮并保存数据,之后用户B执行相同操作。用户B收到错误消息,提示类似于"数据已更新,请重新加载页面"。他重新加载页面并失去他所做的所有更改:(只有在那之后他才能保存他的更改,但他必须再次这样做。
其他可能的情况:用户A和B访问该页面,但只有第一个用户才能保存他的工作,其他用户会看到类似"其他人正在编辑该页面的消息,稍后再试一次"。
对于第一个场景,您可以实现以下内容:表的每一行(在数据库中)都有一个last-update-timestamp,每次更改此行时都会更新为当前时间。
现在,让我们想象用户A在打开页面时获得带有时间戳1
的行,用户B稍微慢了一点,并且时间戳为2
。但是,他更快地完成了他的更改,并先按下保存按钮。现在,该行保存在DB中,时间戳记为5
。用户A正在尝试保存其更改,但其数据的时间戳为1
,这与当前在数据库中的5
不同。这意味着有人已经更改了这些数据,他应该看到我上面提到的错误消息。
第二种情况实施起来有点困难。我认为最好的方法是打开到DB的交易
true
; 现在,如果其他用户请求相同的行,则交易将失败,他将无法开始更改数据。
用户A在保存数据时应将这些locked
标记放回false
。
重要的事情:这些锁应该具有超时功能,以防止用户打开页面并关闭它而不保存(或浏览器崩溃或其他)。您可能还想为同一个用户实施某种锁重新加载 - 当用户第一次打开页面,然后关闭它而不保存数据并再次打开 - 他应该能够编辑数据。这可以通过以某种方式识别用户来完成 - 登录,cookie等。