Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
最佳实践Hibernate乐观锁定和web应用程序_Hibernate_Web Applications_Optimistic Locking_Session Per Request - Fatal编程技术网

最佳实践Hibernate乐观锁定和web应用程序

最佳实践Hibernate乐观锁定和web应用程序,hibernate,web-applications,optimistic-locking,session-per-request,Hibernate,Web Applications,Optimistic Locking,Session Per Request,我有一个用Tapestry5(JavaWebFramework)和Hibernate制作的web应用程序。现在我尝试添加乐观锁定。所以我添加了一个version属性,乐观锁定可以正常工作,这样做既简单又快速 但由于我的web应用程序使用“每请求会话”模式,我不确定使用这种乐观锁定的最佳方式是什么 发生了什么: UserA打开带有表单的页面,表单中加载了entityA(版本1)中的值 UserB打开带有表单的页面,表单中加载了entityA(版本1)中的值 UserA更改一些值并提交表单。 ->新

我有一个用Tapestry5(JavaWebFramework)和Hibernate制作的web应用程序。现在我尝试添加乐观锁定。所以我添加了一个version属性,乐观锁定可以正常工作,这样做既简单又快速

但由于我的web应用程序使用“每请求会话”模式,我不确定使用这种乐观锁定的最佳方式是什么

发生了什么:

UserA打开带有表单的页面,表单中加载了entityA(版本1)中的值

UserB打开带有表单的页面,表单中加载了entityA(版本1)中的值

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

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

应该发生什么

不应提交对UserB的更改。但是由于每个请求的会话模式,Hibernate可能发生乐观锁定错误的时间窗口被减少到从提交到提交之后的新请求的时间跨度,这不是期望的结果

可能的解决方案

经过一些研究,我发现如下:

  • 使用entities版本向表单添加隐藏字段
我可以使用此值在提交之前设置实体的版本,但Hibernate文档不建议设置此值。 此外,它仅在分离并重新附着实体时才起作用,因为否则手动设置的版本值将被Hibernate忽略

其次,我可以使用这个版本值手动检查表单呈现时的版本是否与提交时请求中加载的实体版本相同。然后,如果需要,我自己抛出一个乐观锁定异常

  • 将分离的实体放入HttpSession,这样我就不必在提交时再次加载它
结论

这些方法很有效,但对我来说似乎不太实用,而且很容易出错。
因此,我想知道其他人是如何实现这个问题的。

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

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

只要您可以维护版本,就不需要在程序中手动检查版本,如果让hibernate来做这件事是有效的,因为您无法预测对象层次结构的深度


因此,您可以做的是,如果在web层中使用分离的对象,则必须将版本再次设置为持久实体,然后hibernate将负责共电流控制。

我最终实现了以下功能:

  • 使用entities版本向表单添加隐藏字段
  • 表单dto对象的使用
  • 将这些dto对象附加到httpsession(跨多个请求的会话状态)
  • dto和实际对象之间的手动版本检查