如何防止两个用户从数据库中编辑一行

How to prevent two users to edit one row from DB

我正在使用 Spring/Hibernate/ZK。在一个选项卡中,我从数据库中获取对象供用户编辑,但第二个用户可以打开相同的选项卡和相同的对象进行编辑。我想通过 "This object is аlready open" 之类的消息通知第二个用户并隐藏按钮以进行保存。因此第二个用户可以看到从数据库到该对象的当前数据,但不能编辑 him.Is 有一种方法可以为此检查会话对象或其他方法。

  • 您可能有其他字段指示正在编辑该列。当第一个用户开始工作时,该字段将被更新。第二个用户将查询状态为 'on hold' 的对象,您的代码将处理此问题。
  • 其他方式 - 使用 Hibernate @Version field in your entity. It holds object version which is incremented after every update operation. If second user would save object after first one already saved, it would throw OptimisticLockException which you could handle in your code. More about optimistic and pesimistic locking: Chapter 5. Locking. Related discussions: Hibernate Automatic Versioning and When to use @Version and @Audited in Hibernate?

最好的解决方案是使用带版本控制的乐观并发控制,当 Hibernate 抛出并发更新问题时由于同一行在两个事务中被更新然后使用以下策略之一

  • 先胜策略
  • 最后获胜策略
  • 合并冲突的更新策略

先赢策略不是好的解决方案,因为它会导致更新丢失,用户会因为丢失所有工作而感到沮丧。

通过最后获胜策略,其中一位用户将收到错误消息,表明您正在处理陈旧数据并重新开始您的交易。通过这种方式,用户也会感到沮丧,因为现在他又需要从头开始重新启动操作,但他的更改不会丢失。

而是使用合并冲突的更新策略,当 Hibernate 抛出陈旧对象异常并使用新数据重新加载屏幕时,用户将看到更新的结果并允许他继续使用最新数据。在此用户更改不会丢失,用户也不会收到错误消息,只是他的屏幕会重新加载新数据,他可以决定是否继续。

您可以以任何电子商务网站为例,您将获得最后获胜策略或合并冲突更新策略的结果之一。两个用户可以从一个项目开始,但其中一个用户会在最后一个屏幕中收到消息,指出该项目没有库存。

其他答案主要看数据库,但如果所有用户都使用相同的 zk 应用程序访问数据库,您可以跟踪 ComposerViewModel 中打开的对象(取决于无论您使用 MVC 还是 MVVM;我都将其称为控制器)。

您的控制器需要一个 static 当前修改的对象列表。如果用户请求打开不在列表中的对象,一切都很好,您的控制器启用字段和保存按钮。否则,这些将被禁用 and/or 你会显示一条消息。

棘手的部分是从该列表中清除对象。如果用户按下保存按钮,您只需从列表中删除该对象。但是,如果用户没有关闭选项卡或者他们的会话超时怎么办?在这种情况下你需要一个回调,或者一个定期检查屏幕是否仍然打开的机制。

您可以通过向选项卡添加一个 zk 计时器来实现此目的,该选项卡不时发出 ping 并更新静态列表中的时间戳(因此将其设为地图)。如果新用户尝试编辑该对象,请检查最后一个时间戳的时间。如果它足够旧(即以前的用户保存它或放弃屏幕),允许他们编辑它。

不过,如果用户只是保持屏幕打开,您必须考虑该怎么做。他们被允许在对象上锁定多长时间?这也是 Microsoft Office 中的一个问题。如果多个用户尝试从网络位置打开一个 Excel 文件,第一个将被锁定,其他用户将无法保存,直到该用户保存。