7

如果这是完全重复的,请纠正我,我知道这个话题经常被讨论,但找不到明确的答案。

问题:

在 MVC webapp 中处理 Hibernate 对象的最佳实用解决方案是什么?

细节:

我正在使用 Hibernate,并希望尽可能利用延迟加载。
我正在使用 MVC 风格的 webapp。
我讨厌延迟加载初始化异常。
我讨厌在事务之间重新附加 Hibernate 对象。

选项:

  1. 渴望加载一切
    • 解决了延迟初始化问题,但使我的查询更大
  2. 使用一些“在视图中打开会话”的概念
    • 我喜欢它的简单
    • 对象仍然需要重新附加,并且在 AJAXy 设置中,非常频繁
    • 为每个请求打开一个会话
  3. 在离开交易之前“触摸”我需要的物品
    • 充其量似乎很脆弱..而且乏味
  4. 创建不同的、简化的、“分离的”对象,这样视图就不会看到真正的 Hibernate 对象
    • 这些可能比完整的 Hibernate 对象更简单,因此它不像模型的完整急切加载
    • 我在一些地方听说过这个建议,但似乎更多的责任/代码/工作
  5. 当我想与 Hibernate 对象交互时打开一个会话。
    • 这可以很好地包裹在 Spring Service 层中,但有时似乎过度。例如:我想要hibernateObject.getRelatedObjects()但需要说类似的话springService.getRelatedObjects(hibernateObject)

我错过了什么吗?
我是不是想多了?
我有没有考虑过一些事情?

PS:

对于一个 Web 框架,我正在使用 ZK,但并不真正想要 ZK 特定的答案。
我也在使用 Spring,并且对 Spring 的特定答案很满意,因为它无处不在。

4

3 回答 3

5

使用 4-ish - 不要在视图中使用打开会话,不要让你的休眠实体一直冒泡到视图,而是让转换器在休眠实体和你的域对象或“视图 bean”之间转换,具体取决于你的方式想工作它。

我认为 Hibernate 实体只是一种持久性策略,而不是域模型或 UI 表示。

于 2013-01-16T14:11:34.557 回答
3

有以下三种方式:

为您的属性使用急切的获取负载:如果您有一个大数据表,这可能是一个问题。

使用名为 OpenSessionInView 的过滤器:此过滤器将保持会话打开,直到您的网页完全加载。如果在此加载中请求了任何休眠对象,则将打开会话并避免延迟加载异常。

User VOs(Valueble Objects):在你的应用中,会有2种对象。一个在持久层和业务层之间传递的对象,以及一个供您查看层的对象。例如,UserVO 和 UserModel。vo 将用于在视图和业务层之间传输信息。在您的业务实现中,您将使用 vo 填充模型对象以将其发送到您的持久层。使用这种模式,您不会有更多的延迟加载异常,因为所有需要的信息都会在必要时填充到您的 vo 对象中。

一些参考:
OpenSessionInView
Eager Fetching Load
Hibernate Performance Tips

于 2013-01-16T14:35:16.623 回答
1

将表示层与数据访问层混合是一个设计问题。

您的视图应该通过控制器访问模型,但是通过直接使用 Hibernate 对象,您正在混合层。IMO 数据访问应该是模型之下的另一层。即使您的实体在 xml 中进行了注释或定义,它们本身也与模型分开。

引入封装 Hibernate 逻辑的 Facade 或 Manager,并通过控制器的服务契约公开它,返回表示这些实体的有意义的对象。如果有的话,我会选择选项4。

于 2013-01-16T14:18:20.023 回答