1

所以我有一个使用 Spring MVC + Hibernate 的简单 Web 应用程序,并且正在使用 OpenSessionInViewFilter。我最近一直在考虑用 Flex 或 GWT 之类的东西替换 UI。

起初我认为这很容易,因为我可以从新的前端访问我的服务层。但是当我更多地考虑这一点时,我对延迟加载的问题有点紧张。使用传统的 Web 前端没问题,因为我在视图中使用了开放会话......视图需要加载的所有内容都会在视图构建时加载。

所以假设我有一个方法来返回一个客户,一个客户有一堆联系人,联系人有一堆地址,等等。如果我从我的新“RIA”控制器调用 getCustomer(),它将获得一个客户,但客户的联系人集合只是一个代理或 null。

我可以在已有的基础上创建一个新层,返回预先填充的 DTO……但是……这似乎会变得复杂。

有什么建议吗?

4

2 回答 2

2

您绝对正确,这确实给 RIA 带来了问题。如果您使用的是 OpenSessionInViewFilter,则数据不会返回 null;相反,序列化程序将遍历整个对象图并发送回大量数据。这将引入严重的性能问题。

引入一个单独的 DTO 层为您提供了很多控制,因为您可以确保序列化程序只遍历您构建的对象;您可以确保它们不包含惰性代理。不幸的是,这在编写实体和 DTO 之间的映射代码时引入了一些乏味,但它确实让您可以完全控制做任何您想做的事情。

另一种方法是在为序列化准备对象图的序列化程序之前引入一个层。我们在过去的一些项目中使用的一种方法是向服务层引入一个方面,该方面将遍历整个对象图并用仅具有 @Id 属性集的实体的新实例替换惰性代理。如果该图在以后被保存回来,这将确保 @ManyToOne 关系不会无意中为空。您可以调用 getter 或使用 Hibernate.initialize() 来强制初始化您想要通过网络发送的数据。当您在 Hibernate 中引入 @OneToMany 或 @ManyToMany 关系的级联保存时,这确实会变得更加复杂。

我最近遇到了一种名为 Gilead 的解决方案,旨在解决这个问题。它使用与上述类似的方法:

http://noon.gilead.free.fr/gilead/

我也相信 Granite DS 作为其 Tide 框架的一部分可以解决这个问题:

http://www.graniteds.org/confluence/display/DOC/4.+Lazy+Initialization

我认为没有人解决的一个问题是一种从服务器实际延迟加载 RIA 数据的方法。我认为这当然可以完成,但这里有一些安全问题。您需要进行非常强大的安全检查,以确保任何延迟加载数据的尝试都来自实际上有权加载该数据的用户。

于 2009-06-06T17:23:43.753 回答
0

如果您的表示层需要存在客户联系人,则数据层将提供它。延迟加载的目的不是省略数据……它在计算机编程中用于将对象的初始化推迟到需要它的时候。

你不必担心。

于 2009-06-06T00:17:19.110 回答