Spring 一对多关系中带弹簧靴的无限循环
在rest应用程序中,我使用SpringBoot和jpa 我有一个班级寄宿生 谁有Spring 一对多关系中带弹簧靴的无限循环,spring,spring-boot,spring-restcontroller,Spring,Spring Boot,Spring Restcontroller,在rest应用程序中,我使用SpringBoot和jpa 我有一个班级寄宿生 谁有 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger") private List<Reference> referenceList; 当我调用这个方法时 @RequestMapping(value = "/lodgers/{lodgerId}", method = RequestMethod
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
当我调用这个方法时
@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"]...
当您在返回对象中有一个循环,并且spring试图将其序列化为其他类型时,就会发生这种情况
尝试从返回的模型中创建不带周期的DTO或值对象(简单POJO),然后返回它。不要通过REST webservice返回具有循环依赖关系的实体-创建新的DTO类,映射从数据库中获取的实体,并在webservice中返回它 更多信息请点击此处:
当然,如果您愿意,您可以使用另一个映射库,我个人最喜欢的是Orika()让我们假设您的代码如下所示:-
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 + "]";
}
当您注意到在两个POJO中都编写了toString()方法时,您将看到我们正在从任意一方调用两个类的toString(),这导致从任意一方调用toString()方法的次数都是无限的,并且永远不会终止。为了避免这种情况,请从reference.class的toString()中删除任何引用[您也可以从Lodger类中删除。]因此,reference类的toString()中不会包含Lodger属性
最后,您的参考类将如下所示:-
参考类
@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 + "]";
}
@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 + "]";
}
解决方案:
使用
@JsonManagedReference
第一个实例化对象的注释
@JsonBackReference
第二个实例化对象的注释
第一:
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "lodger")
private List<Reference> referenceList;
如果两个表中的主键名称相同,例如:id 加上这个
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class User {
...
}
和参考类
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Reference {
...
}
有关参考,请参阅
您唯一需要的是,在您拥有注释的类中,使用希望在值部分跳过的属性实现下一个注释
@JsonIgnoreProperties(值={“yourtattribute”、“handler”、“hibernateLazyInitializer”},allowSetters=true)
我为您的代码举了一个例子->
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties(value = {"referenceList", "handler","hibernateLazyInitializer"}, allowSetters = true)
@JoinColumn(name = "lodgerId")
private Lodger lodger;
您在
@JsonIgnoreProperties
上的值部分中放置的所有属性都将被忽略,有了它,您可以解决无限循环,并在将来将其用于具有相同格式的其他开发。您将在此处找到最佳解决方案。如果您尚未获得解决方案,请发表意见。但这不会从第二个对象中给我lodgerId。此解决方案解决了主要问题,但产生了另一个问题问题是,现在我们根本没有得到第二个被引用的对象。你能在示例中解释更多关于这个的信息吗!
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id")
public class Reference {
...
}
@JsonIgnoreProperties({"hibernateLazyInitializer","referenceList"}) at class Level
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnoreProperties(value = {"referenceList", "handler","hibernateLazyInitializer"}, allowSetters = true)
@JoinColumn(name = "lodgerId")
private Lodger lodger;