在休息应用程序中,我使用带有jpa的spring boot。
我有一个Lodger班级
谁拥有
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
在我的班级参考中,我有
@ManyToOne
@JoinColumn(name = "lodgerId")
private Lodger lodger;
当我打电话给这个方法时
@RequestMapping(value = "/lodgers/{lodgerId}", method = RequestMethod.GET)
public Lodger getLogderById(@PathVariable("lodgerId") long lodgerId) {
return lodgerService.getLodger(lodgerId);
}
我收到此错误
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: server.bean.Lodger["referenceList"]->org.hibernate.collection.internal.PersistentBag[0]->server.bean.Reference["lodger"]->server.bean.Lodger["referenceList"]->org.hibernate.collection.internal.PersistentBag[0]->server.bean.Reference["lodger"]->server.bean.Lodger["referenceList"]...
答案 0 :(得分:10)
解决方案:
使用
实例化的第一个对象的 @JsonManagedReference
注释
@JsonBackReference
注释
首先:
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
第二
@JsonBackReference
@ManyToOne
@JoinColumn(name = "lodgerId")
private Lodger lodger;
答案 1 :(得分:4)
当你在返回对象中有一个循环并且spring尝试将它序列化为其他类型时会发生这种情况。
尝试创建DTO或Value Object(简单POJO),不返回返回的模型,然后返回它。
答案 2 :(得分:1)
如果两个表中的主键都是相同的名称,例如:id。
添加此
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class User {
...
}
参考类。
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Reference {
...
}
答案 3 :(得分:1)
您唯一需要的是,在您具有注释 @ManyToOne
的类中,使用您要在值部分中跳过的属性实现下一个注释
@JsonIgnoreProperties(value = {"yourAttribute", "handler", "hibernateLazyInitializer"}, allowSetters = true)
我为你的代码举了一个例子 ->
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties(value = {"referenceList", "handler","hibernateLazyInitializer"}, allowSetters = true)
@JoinColumn(name = "lodgerId")
private Lodger lodger;
您在 @JsonIgnoreProperties
上的值部分中放置的所有属性都将被忽略,这样您就可以解决无限循环并将其用于将来具有相同格式的其他开发。
答案 4 :(得分:0)
不要通过REST webservice返回具有循环依赖关系的实体 - 创建新的DTO类,映射从数据库获取的实体并将其返回到webservice中。
此处有更多信息:http://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application
当然如果你想要你可以使用另一个地图库,我个人最喜欢的是Orika(http://orika-mapper.github.io/orika-docs/intro.html)
答案 5 :(得分:0)
让我们假设您的代码如下所示: -
Lodger.class
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
public List<Reference> getReferenceList() {
return referenceList;
}
public void setReferenceList(List<Reference> referenceList) {
this.referenceList = referenceList;
}
@Override
public String toString() {
return "Lodger[referenceList=" + referenceList + "]";
}
Reference.class
@ManyToOne
@JoinColumn(name = "lodgerId")
private Lodger lodger;
public Lodger getLodger() {
return lodger;
}
public void setLodger(Lodger lodger) {
this.lodger = lodger;
}
@Override
public String toString() {
return "Reference[lodger=" + lodger + "]";
}
当您注意到在两个POJO中编写的toString()方法时,您将看到我们从两侧调用两个类的toString(),这导致无限的no。调用来自双方的toString()方法永远不会终止。要避免这种情况,请从Refernce.class的toString()中删除任何引用[您也可以从Lodger类中删除。]因此Reference类的toString()中不会包含lodger属性。
所以最后你的Reference类看起来像: -
Reference.class
@ManyToOne
@JoinColumn(name = "lodgerId")
private Lodger lodger;
public Lodger getLodger() {
return lodger;
}
public void setLodger(Lodger lodger) {
this.lodger = lodger;
}
@Override
public String toString() {
return "Reference[Properties other than lodger=" + properties other than lodger + "]";
}
答案 6 :(得分:0)
@JsonIgnoreProperties({"hibernateLazyInitializer","referenceList"}) at class Level
有关参考,请参见this article on medium.com。