根据Java 持久/锁定 wiki 书籍 http://en.wikibooks.org/wiki/Java_Persistence/Locking#Common_Locking_Mistakes.2C_Questions_and_Problems*,处理锁的最好方法是向用户报告乐观锁错误/异常。
问题是它不可扩展。假设我有很多用户,他们可能会通过相同的操作导致锁定。用户不关心锁定错误消息。
简而言之 :
- 最好的方法是禁用所有锁?
- 最好的方法是向用户报告错误锁定消息?但用户必须重试他的操作,直到它起作用!
- 最好的方法是重试事务,直到没有锁?
*
处理乐观锁异常
不幸的是,程序员常常为了自己的利益而变得过于聪明。使用乐观锁时出现的第一个问题是发生 OptimisticLockException 时该怎么办。友好邻居超级程序员的典型反应是自动处理异常。他们只会创建一个新事务,刷新对象以重置其版本,然后将数据合并回对象并重新提交。问题很快就解决了,是吗?
这实际上从一开始就违背了锁定的全部意义。如果这是您想要的,您也可以不使用锁定。不幸的是,OptimisticLockException 很少会被自动处理,并且您确实需要就这个问题打扰用户。您应该向用户报告冲突,并要么说“抱歉,但发生了编辑冲突,他们将不得不重做工作”,或者在最好的情况下,刷新对象并向用户提供当前数据和他们提交的数据并帮助他们在适当的情况下合并两者。
一些自动合并工具会比较数据的两个冲突版本,如果各个字段都不冲突,则数据将自动合并,无需用户的帮助。这就是大多数软件版本控制系统所做的。不幸的是,用户通常比程序能够更好地决定何时发生冲突,仅仅因为 .java 文件的两个版本没有更改同一行代码并不意味着不存在冲突,第一个用户可能已经删除了其他用户添加了要引用的方法的方法,以及导致通常每晚构建经常中断的其他几个可能的问题。
用户会关心这个消息,因为他想做一些修改,而修改还没有进行。因此,他将刷新页面以查看数据的新状态,并将重做他的修改,或者决定在新状态下不再进行修改。
如果两个用户同时修改一个实体,并且无论修改是什么,如果最后一个修改获胜,这会出现问题吗?如果出现问题,请使用乐观锁定,并在出现问题时通知用户。没有办法解决这个问题。
如果这不是问题,那么就不要使用乐观锁。如果最后的修改没有破坏数据库中的约束,那么它总是会获胜。但是并发用户修改相同的数据会always导致异常(例如,因为某些用户可能会在其他用户提交对同一实体的修改之前删除该实体)。
重试不是一个选择:
- 要么它会再次失败,因为不可能进行修改
- 或者它会成功,但会首先破坏乐观锁定的意义。
您的问题可以用汽车类比来解释。假设您选择购买带有限速器的汽车,以确保您不会超速。现在你问:但我不在乎速度限制。我不应该总是禁用限速器吗?可以,但是如果您被警察抓住,请不要感到惊讶。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)