我的家长班:
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> child;
public List<Child> getChild() {
return child;
}
public void setChild(List<Child> child) {
this.child = child;
}
我的孩子班:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REF_ID")
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
错误:
Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:626) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:211) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
at javax.servlet.ServletResponseWrapper.getWriter(ServletResponseWrapper.java:109) ~[tomcat-embed-core-8.5.15.jar:8.5.15]
at org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$SpelView.render(ErrorMvcAutoConfiguration.java:227) ~[spring-boot-autoconfigure-1.5.4.RELEASE.jar:1.5.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.9.RELEASE.jar:4.3.9.RELEASE]
... 38 common frames omitted
在浏览器中:
它看起来像@OneToMany来自调用子对象的父实体。但是@ManyToOne在子实体中通过再次调用父对象并重复它来做同样的事情。如何避免这个问题?
答案 0 :(得分:3)
我会这样使用@JsonManagedReference和@JsonBackReference:
@JsonBackReference
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> child;
@JsonManagedReference
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REF_ID")
private Parent parent;
这与JPA无关。您的@Entity模型提供了访问字段的方法。要在API中表示它们,请对它们进行序列化。序列化程序不知道该级别的实体(它将知道持久层的位置。这将违反SRP)。因此,您必须像在实体模型上使用@ManyToOne,@ OneToMany一样提供序列化程序提示。序列化程序遍历您的类上的get方法,并调用它们。如果没有提示,您最终会得到循环引用,因为您调用父项,然后获取子项。序列化孩子后,再次给父母打电话。
@JsonManagedReference:用于表示带注释的属性是字段之间双向链接的一部分的注释;并且它的作用是“父”(或“前进”)链接。
@JsonBackReference:用于指示关联属性是字段之间双向链接的一部分的注释;并且它的作用是“child”(或“back”)链接
答案 1 :(得分:2)
在您的子课程中,忽略使用@JsonIgnore
序列化/绝望您的父级@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REF_ID")
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
答案 2 :(得分:0)
从可接受的答案中提出的注释和其他注释基本上是在告诉Spring Boot跳过阅读它们的方法。是的,它能够解决循环问题,但不能完全解决返回预期的json输出的问题。
相反,我对这些实现做了一些改动,对我有用!
交换参考注释
代码段示例:
Parent.java(类)
@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL) //"parent" -> is the name defined by child class
private List<Child> childs;
Child.java(类)
@JsonBackReference
@ManyToOne
@JoinColumn(name = "parent_id") //parent_id is the foreign key for child
private Parent parent; //object name defined from Parent class
上面的互换对我有用。