问题描述:当我们使用JPA聚合关系:多对多(@ManyToMany),多对一(@ManyToOne)(一对多)这两种关系管理实体时,Controller里采用@ResponseBody返回实体时(@OneToOne没事),会发生循环解析实体,可能导致产生的数据错误或者后台异常。
例如:员工(Staff) 、部门(Department) 、项目(Project)
Staff和Department关系:@ManyToOne(多个员工属于一个部门)
Department和Staff关系:@OneToMany(一个部门有多个员工)
Staff和Project关系:@ManyToMnay(一个员工可能忙多个项目,一个项目也可能含多个员工)
当我们RestController层通过id查询单个员工时,返回Staff实体的json时,就会产生问题(以多对一关系为例子):
Json解析Staff类:Staff类包含Department类(@ManyToOne),然后去解析Staff里的Department类,结果Department里还有Staff实体(@OneToMany),又返回来解析Staff实体,Staff类又包含Department类....造成死循环。
问题解决:
其实我们可以换个思路去思考这个问题:
(1)我们获取一个员工(Staff)信息时,关不关心他的部门(Department)是什么,他在忙什么项目(Project)。
(2)当我们获取一个部门信息时,关不关心部门下所有的员工信息。
我觉得我比较关心(1),不太关心(2),不关心(2)的原因是,如果我想获取一个部门下的所有员工时,我可以单独去查这个部门的所有员工,而没必要去获取部门信息时就把所有员工信息都返回。
jackson也为我们设置了这样的注解:@JsonManagedReference @JsonBackReference
@JsonManagedReference:引用的管理方
@JsonBackReference:返回引用管理方
我们把@JsonManagedReference放到Staff类的Department属性上同时把@JsonBackReference放到Department类的List<Staff>属性上,就是告诉jackson不要循环解析啦,Staff是管理方要展示Department,而Department要返回引用管理方。最后的结果就是Staff的json里含Department的信息,如果单独查询Department实体时不会出现Staff的信息。