22

我对循环参考有疑问。

我有将对象返回到前端的 Rest Webservices,问题是当我尝试返回具有多个引用的对象时,结果我得到了无限响应,这会生成

java.lang.IllegalStateException: 
    Cannot call sendError() after the response has been committed

这些对象是由 Hibernate Code Generation 自动生成的,我需要在后端有循环引用,我只需要在使用 Jackson 将信息发送到前端之前将其删除。

控制器方法头是:

@RequestMapping(value="/list", method=RequestMethod.POST)
public @ResponseBody eventResponse list(@RequestBody String sessionID) {

我没有做任何明确的转换为 Json 的事情,我是一个新手,我认为杰克逊自动解决了这个问题。

4

3 回答 3

44

有两种方法可以解决这个问题。如果您必须将您的实体暴露给外界,我建议添加@JsonIgnore导致循环引用的属性。这将告诉杰克逊不要序列化该属性。

另一种方法是使用 Jackson 提供的双向功能。您可以使用@JsonManagedReference@JsonBackReference@JsonManagedReference是属性的“转发”部分,它将正常序列化。@JsonBackReference是引用的“后面”部分;它不会被序列化,但会在“转发”类型被反序列化时重建。

您可以在此处查看示例。

这解决了您的评论:我认为在这种情况下您可能想要做的是使用外部世界可见的 DTO。我喜欢这种方法,因为我不想将我的实体暴露在外面。这意味着 Jackson 注释将在 DTO 上而不是在实体上。您将需要某种将实体转换为 DTO 的映射器或转换器。现在,当您对实体进行更改时,除非您修改映射器/转换器,否则它们不会传播到 DTO。我认为这没关系,因为当您对实体进行更改时,您可以决定是否要公开该更改。

更新

这里有一篇很好的博客文章,详细介绍了在 Jackson 中处理双向关系的各种方法。它还描述了使用@JsonIgnore,@JsonManagedReference@JsonBackReference,@JsonIdentityInfo以及@JsonView自定义序列化程序的解决方案。这是您可以使用的各种技术的非常全面的文章。

于 2013-06-30T19:03:44.797 回答
9

一个注解@JsonIdentityInfo就解决了这个问题。它也处理循环引用。参考

于 2015-10-21T13:21:19.463 回答
0

@JsonbTransient 解决了我处理循环引用的问题:

@JsonbTransient // javax.json.bind.annotation.JsonbTransient
@ManyToOne
@JoinColumn(name = "userId", referencedColumnName = "id", nullable = false)
public AContainedEntity getAContainedEntity() {
       return aContainedEntity;
}
于 2020-01-05T20:57:44.107 回答