Spring Boot 1.5.10关联查询抛出getOutputStream()已调用异常求助
这个问题我之前排查过好多次,大概率是Product和Service的双向关联引发了JSON序列化循环引用!咱们一步步拆解:
问题原因分析
当services表有数据时,你的Product类里应该有List<Service>的一对多关联,而Service类里又有Product的多对一关联(双向绑定)。Jackson序列化Product的时候,会去序列化它关联的ListgetOutputStream() has already been called for this response异常;而服务表为空时,没有关联数据可以序列化,自然不会触发这个循环,所以接口正常。
具体解决方案
针对Spring Boot 1.5.10的版本,有两种常用的解决方式:
1. 用@JsonIgnore忽略反向关联的序列化
在多对一的一端(Service类的Product字段)加上@JsonIgnore注解,直接跳过该字段的序列化,从根源切断循环:
@Entity public class Service { // 其他字段定义 @ManyToOne @JsonIgnore // 序列化Service时忽略关联的Product private Product product; // getter、setter方法 }
2. 用@JsonManagedReference和@JsonBackReference处理双向关联
如果需要保留双向关联的序列化逻辑(比如某些场景下需要从Service端获取Product信息),可以用Jackson专门的双向关联注解:
- 在一对多的Product端标注
@JsonManagedReference(被管理的主动端,会正常序列化) - 在多对一的Service端标注
@JsonBackReference(反向端,序列化时会被忽略,避免循环)
示例代码:
@Entity public class Product { // 其他字段定义 @OneToMany(mappedBy = "product") @JsonManagedReference private List<Service> services; // getter、setter方法 } @Entity public class Service { // 其他字段定义 @ManyToOne @JsonBackReference private Product product; // getter、setter方法 }
额外排查点
如果上面的方法没解决问题,再检查下你的控制器方法:有没有同时使用@ResponseBody(或@RestController)又手动调用response.getOutputStream()写数据?这种重复输出的操作也会触发这个异常,但结合你的场景,这个概率比较低。
内容的提问来源于stack exchange,提问作者Mohammed Mostafa

