0

我正在使用 Hibernate 4.1 和 Spring 3.1。

考虑以下 User 类具有对包括 self 在内的其他对象的引用。我定义的所有休眠映射都是 LAZY 的,所以只有当我在 jsp 或其他代码中使用它们时才会加载引用对象。

class User {
  private User createdBy;
  private Department department;
  private Project project;
  .....
  .....
}

问题是当我想返回一个 JSON 表示时,它使用反射来完成它并在那里进行深度序列化。下面是我的控制器代码。

@ResponseBody
public User getUser(int id) {
  User user = [fetch user from service];
  return user;
}

因为我也有自我参考,所以它进入了无限循环。

解决这个问题的解决方案是什么?我知道我需要在返回 UserDTO 的地方使用 DTO 模式,但我创建了多少这样的方法。例如,在一个地方我只需要基本的用户属性,在另一个地方我需要用户及其部门,在另一个地方我需要用户与部门和项目。

我需要公开多少这样的方法。有没有其他方法可以解决这个问题?

4

3 回答 3

1

问题是您有一个循环引用,而您的 JSON 编码器没有处理它。因此,您需要手动处理它。

按照您的评论创建 DTO 会有所帮助。您可以为所需的每个解码级别使用一种方法实现 Helper。

您可以使用BeanUtils将每个属性从一个 bean 复制到另一个。

另一个解决方案(更具概念性)是:

为每个边界方法实现一种装饰器,并在结果上应用推土机。你可以在这里举一个例子

装饰或多或少像这样发生:

public interface Controller {
   User getUser(int id);
}

public class RealController {
   public User getUser(int id) {
      return dao.getUser(id);
   }
}

public class DecoratedController {

   private Controller realController;

   public User getUser(int id) {
      // here you will apply dozer or do it manually creating an object with so deep as you wish
      return flatUserStructure(realController.getUser(id));
   }
}
于 2012-07-02T09:11:10.573 回答
0

为了能够调整 Hibernate 关联加载,您可以使用fetch join,请阅读14.3。关联和连接

为避免深度序列化问题,您可以创建适当的 DTO 并使用诸如Jackson Java JSON 处理器项目的@JsonIgnore注释之类的东西对其进行调整。

于 2012-07-02T09:21:04.990 回答
0

我认为问题由两部分组成:

JSON 自定义序列化:您可以使用这种方法来避免UserDTOUser. 但是,您仍然应该将 JSON 序列化程序定义为 bean 或可配置的服务对象,以便您可以命令它在不同的控制器方法映射中序列化什么。一个很好的例子可以在这里找到。

Spring 配置:下一步是配置 spring 以使用您的客户 JSON 序列化程序。因此,当使用 时@ResponseBody,Spring 将使用您的自定义 JSON 序列化程序。很好的例子可以在这里那里找到。

于 2012-07-02T09:23:32.550 回答