springmvc用jackson返回json无限循环

知兮丶青 spring
阅读(1461) 2018-01-21
springmvc用jackson返回json无限循环
springmvc用jackson返回json无限循环

springmvc使用jackson转json解决双向关联关系(例如一对多)循环调用。目前只是避开了循环调用,并不是真正的从根本上解决。就算用ObjectMapper Hibernate4Module也是解决懒加载转json的问题。



问题简说

实体类:老师Teacher.java

@OneToMany(fetch= FetchType.LAZY,cascade = CascadeType.ALL)
@JoinColumn(name="teacher_id")
public Set<Student> getStudents() {
    return students;
}

实体类:学生Student.java

@ManyToOne
@JoinColumn(name="teacher_id")
public Teacher getTeacher() {
    return teacher;
}

服务层:学生服务层StudentServiceImpl.java

@Override
@Transactional(readOnly = true)
public Student findById(Long id){
    Student student = studentRepository.findOne(id);
    //模拟用到了关联数据,或者使用了自动映射复制到vo、dto等等
    Teacher teacher = student.getTeacher();
    Set<Student> students = teacher.getStudents();
    System.out.println(students);
    return student;
}

控制层:返回json数据到前台

@RequestMapping(value = "/find", method = RequestMethod.GET)
@ResponseBody
public Student find(HttpServletRequest request, HttpServletResponse response){
    Student student = studentService.findById(1L);
    return student;
}


由于hibernate双向关联关系,查出来的实体对象返回前台输出json,会循环嵌套。如:

{"id":1,"name":"Student-1","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":[{"id":2,"name":"Student-2","teacher":{"id":1,"name":"Teacher","students":...
......
......

hibernate双向关联关系转json循环嵌套.png



解决方法

1、最简单的办法

在返回的时候吧循环嵌套设置为空,或mapping转vo,dto的时候过滤该字段。

缺点:对象复杂时比较麻烦,用mapper复制对象又要考虑过滤字段操作。

Student student = studentRepository.findOne(id);
Teacher teacher = student.getTeacher();
teacher.setStudents(null);
return student;

输出:

{"id":1,"name":"Student-1","teacher":{"id":1,"name":"Teacher","students":null}}


2、springmvc返回jackson注解处理

@JsonBackReference:

标记在子类对父类的引用变量上,标注的属性在将对象转换为json数据时,会被忽略。

它的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。

@JsonManagedReference:

标记在父类对子类的引用变量上,标注的属性在被对象转换为json数据时,不会被忽略。

如果没有它在json数据转换为对象时,不会注入@JsonBackReference标记属性。

@JsonIgnore:

直接忽略某个属性,以断开无限递归,序列化或反序列化均忽略。

缺点:学生类找不到老师类的ID了,整个属性都被忽略掉了,如果需要,要另外起属性定义赋值如return teacher.getId();

用户类(子)多的一端

@JsonBackReference
private Teacher teacher;

老师类(父)一的一端

@JsonManagedReference
private Set<Student> students;

输出:

{"id":1,"name":"Student-1"}



后面如果发现有更好的办法再补上。



原创文章,转载请注明出处:https://www.weizhixi.com/article/64.html