4

我有一个使用Tapestry5(java webframework)和Hibernate制作的Web应用程序。现在我试图添加乐观锁定。所以我添加了一个版本属性和乐观锁定工作,所以这很容易和快速。最佳实践Hibernate乐观锁定和Web应用程序

但是,由于我的web应用程序使用“session-per-request”模式,我不确定使用此乐观锁定的最佳方式是什么。

会发生什么:

用户A打开页面,其中已赋值从entityA形式(第1版)。

UserB用加载了entityA(版本1)中的值的表单打开页面。

UserA更改一些值并提交表单。 - >新请求检索entityA(版本1)并提交更改(entityA现在为版本2)

UserB更改一些值并提交表单。 - >新请求检索entityA(版本2),并承诺改变(entityA现在是第3版)

应该发生用户B的

的变化不应该犯了什么。但是由于session-per-request模式,Hibernate发生乐观锁定错误的时间窗口可能会缩短到提交后的新请求的时间范围内,这不是所期望的结果。

可能的解决方案

经过一番研究,我发现了以下内容:

  • 隐藏字段添加到窗体与实体版本

我可以用这个值来设置提交之前的实体版本,但Hibernate文档不建议设置此值。 另外它只在实体分离并重新连接时才起作用,否则手动设置的版本值将被Hibernate忽略。

其次我可以使用这个版本值来做一个手动检查,如果表单呈现时的版本与提交请求中加载的实体版本相同。然后根据需要自己抛出一个OptimisticLockingException。

  • 将分离的实体到HttpSession中,所以我不必再重新装上提交

结论

这些方法的工作,但似乎没有太大的实用我很容易犯错误。 所以我想知道其他人是如何实现这个问题的。

回答

1

我最终实现以下:

  • 隐藏字段添加到窗体与实体版本
  • 形式DTO的使用对象
  • 附加这些DTO对象到HttpSession(会话状态跨越多个请求)
  • dto和实际对象之间的手动版本检查
0

当您将一个持久实体分离出来以将其转移到Web层时,例如创建DTO以将对象传输到Web层。在这种情况下,我们将使用getter和setter将Entity对象转换为DTO对象。

如果您需要使用乐观锁定维护并发控制,则必须在应用程序中维护版本号(与手动设置版本号不同)。否则,我们无法指示休眠什么是旧版本的加载记录。在hibernate文档中,它说:“使断开连接的Session保持接近持久层,使用EJB有状态会话bean将会话保存在三层环境中,不要将其转移到Web层,或者将其序列化到单独的层,将其存储在HttpSession中。“但是,所有环境都没有业务层中的EJB有状态会话bean。在这种情况下,我们必须保持版本号。

只要你可以维护版本,你不需要手动检查程序中的版本,如果你让hibernate做到这一点是非常有效的,因为你无法预测对象层次的深度。

所以你可以做的就是如果你在web层使用分离的对象,你必须再次将版本设置为持久化实体,然后hibernate将负责Cocurrency控制。

相关问题