我正在使用并发布循环参考。
我有Rest Webservices将对象返回到前端,问题是当我尝试返回具有多个引用的对象时,结果我得到无限响应,生成
java.lang.IllegalStateException:
Cannot call sendError() after the response has been committed
对象是由Hibernate代码生成自动生成的,我需要在后端使用循环引用,我只需要在使用Jackson将信息发送到前端之前将其删除。
控制器方法标题是:
@RequestMapping(value="/list", method=RequestMethod.POST)
public @ResponseBody eventResponse list(@RequestBody String sessionID) {
我没有做任何明确的转换为Json,我是一个新手,我认为杰克逊自动解决了这个问题。
答案 0 :(得分:32)
有两种方法可以解决这个问题。如果您必须将您的实体暴露给外界,我建议在导致循环引用的属性上添加@JsonIgnore
。这将告诉杰克逊不要序列化该财产。
另一种方法是使用Jackson提供的双向功能。您可以使用@JsonManagedReference
或@JsonBackReference
。 @JsonManagedReference
是属性的“前向”部分,它将正常序列化。 @JsonBackReference
是参考文献的“后退”部分;它不会被序列化,但会在“转发”类型被反序列化时重建。
您可以查看示例here。
这解决了您的评论:我认为在这种情况下您可能想要做的是使用外部世界可见的DTO。我喜欢这种方法,因为我不想将我的实体暴露给外面。这意味着杰克逊的注释将在DTO而不是在整体上。您需要某种将实体转换为DTO的映射器或转换器。现在,当您对实体进行更改时,除非您修改映射器/转换器,否则它们不会传播到DTO。我认为这没关系,因为当您对实体进行更改时,您可以决定是否要公开更改。
<强>更新强>
有一篇很好的博客文章here详细介绍了处理杰克逊双向关系的各种方法。它描述了使用@JsonIgnore
,@JsonManagedReference
和@JsonBackReference
,@JsonIdentityInfo
,@JsonView
以及自定义序列化程序的解决方案。这是您可以使用的各种技术的全面综述。
答案 1 :(得分:7)
单个注释@JsonIdentityInfo
解决了问题。它也处理循环引用。Reference
答案 2 :(得分:0)
@JsonbTransient解决了我处理循环引用的问题:
@JsonbTransient // javax.json.bind.annotation.JsonbTransient
@ManyToOne
@JoinColumn(name = "userId", referencedColumnName = "id", nullable = false)
public AContainedEntity getAContainedEntity() {
return aContainedEntity;
}