您绝对正确,这确实给 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 数据的方法。我认为这当然可以完成,但这里有一些安全问题。您需要进行非常强大的安全检查,以确保任何延迟加载数据的尝试都来自实际上有权加载该数据的用户。