Web应用程序中的并发控制

时间:2014-10-31 14:29:01

标签: java spring spring-mvc jpa concurrency

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

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

id | value | column | row | ...

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

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

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

对于第一个场景,您可以实现以下内容:表的每一行(在数据库中)都有一个last-update-timestamp,每次更改此行时都会更新为当前时间。 现在,让我们想象用户A在打开页面时获得带有时间戳1的行,用户B稍微慢了一点,并且时间戳为2。但是,他更快地完成了他的更改,并先按下保存按钮。现在,该行保存在DB中,时间戳记为5。用户A正在尝试保存其更改,但其数据的时间戳为1,这与当前在数据库中的5不同。这意味着有人已经更改了这些数据,他应该看到我上面提到的错误消息。

第二种情况实施起来有点困难。我认为最好的方法是打开到DB的交易

  • 读取我们想要的行;
  • 放了一些标记,如"锁定"所有人都true;
  • 如果某行已被锁定,则失败(或返回可用行,具体取决于您的需要)。但是,可能应该失败;
  • 将行返回到jsp页面;

现在,如果其他用户请求相同的行,则交易将失败,他将无法开始更改数据。

用户A在保存数据时应将这些locked标记放回false重要的事情:这些锁应该具有超时功能,以防止用户打开页面并关闭它而不保存(或浏览器崩溃或其他)。您可能还想为同一个用户实施某种锁重新加载 - 当用户第一次打开页面,然后关闭它而不保存数据并再次打开 - 他应该能够编辑数据。这可以通过以某种方式识别用户来完成 - 登录,cookie等。