带有弹簧启动的无限循环,具有一对多的关系

时间:2015-06-17 12:56:16

标签: spring spring-boot spring-restcontroller

在休息应用程序中,我使用带有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"]...

7 个答案:

答案 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

enter image description here