错误提示:

2020-04-23 22:50:53.363  WARN 11316 --- [nio-8001-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failure while trying to resolve exception [org.springframework.http.converter.HttpMessageNotWritableException]

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
	at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
	at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.sendServerError(DefaultHandlerExceptionResolver.java:550) ~[spring-webmvc-5.2.5.RELEASE.jar:5.2.5.RELEASE]
	at org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleHttpMessageNotWritable
	......
2020-04-23 22:50:53.395 ERROR 11316 --- [nio-8001-exec-1] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/user/users] and exception [Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.hibernate.collection.internal.PersistentBag[0]->com.itzhiya.first.jpa.demo.users.UserEntity["books"]-......
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

错误分析:
在将数据转为JSON返回时,出现了StackOverflowError,说明数据陷入了死循环。
原因如下:类A中有属性类型为List b;类A与类B为多对多的关系,当类B中没有类型为List的属性时,数据正常返回,但是当类B中存在A的List时,程序陷入死循环。因此判定,当程序从A中获取B的List时,系统会去B中,但是B中也有A中,于是系统又去A中执行,于是递归形成环路,导致系统陷入死循环。

解决方法:
1. 避免代码中互相包含

a)删除A或者B中其中一个属性
b) 在允许序列化的属性上使用@JsonManagedReference,另一个类中属性上使用@JsonBackReference,但是这样一来标注@JsonBackReference的属性将不会被序列化,即它的值不会被返回。

2. 无法避免代码中互相包含的情况

有时候根据需求,我们需要从A中获取B的信息,同时也需要从B中获取A的信息,这种情况下,可以在任意一个类中的属性上增加下面注解:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = “uid”)

这里uid为属性对应的对象表中的主键名称