域模型到JSON - 深度序列化的问题

时间:2012-07-02 08:59:56

标签: java spring hibernate domain-model

我正在使用Hibernate 4.1和Spring 3.1。

考虑以下User类引用其他对象,包括self。我定义的所有hibernate映射都是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;
}

由于我有自引用,它也会进入无限循环。

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

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

3 个答案:

答案 0 :(得分:1)

问题是你有一个循环引用,你的JSON编码器没有处理它。所以,你需要手动处理它。

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

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

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

为每个边界方法实现一种装饰器,并在结果上应用dozer。您可以采用here

的示例

装饰或多或少地出现:

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));
   }
}

答案 1 :(得分:0)

为了能够调整Hibernate关联加载,您可以使用获取加入,请阅读14.3. Associations and joins

为了避免深度序列化问题,您可以创建适当的DTO并使用@JsonIgnore项目的Jackson Java JSON-processor注释等内容进行调整。

答案 2 :(得分:0)

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

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

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