所以我有一个使用Spring MVC + Hibernate的简单Web应用程序,并且正在使用OpenSessionInViewFilter。我最近一直在考虑用Flex或GWT替换UI。
起初我认为这很简单,因为我可以从新的前端点击我的服务层。但是当我考虑到这一点时,我对于延迟加载的问题有点紧张。使用传统的Web前端没有问题,因为我在视图中使用开放会话...在构建视图时,需要加载视图的所有内容。
所以,假设我有一个返回客户的方法,一个客户有一堆联系人,联系人有一堆地址,依此类推。如果我从我的新“RIA”控制器调用getCustomer(),它将获得一个客户,但客户的联系人集合将只是一个代理或无效。
我可以在我已经获得的东西之上创建一个新图层,它返回预先填充的DTO ......但是......看起来它会变得复杂。
有什么建议吗?
答案 0 :(得分: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数据的方法。我认为它当然可以完成,但这里有一些安全问题。您需要非常强大的安全检查,以确保任何延迟加载数据的尝试都来自实际上有权首先加载该数据的用户。
答案 1 :(得分:0)
如果您的表示层需要客户联系人,则数据层将提供该联系人。 lazy loading的目的不是省略数据......它在计算机编程中用于推迟对象的初始化,直到需要它为止。
你不必担心。