首页 > 解决方案 > JPA 未获取数据引发 stackoverflow 错误

问题描述

我有一个非常大的 json 来存储,我将它分成以下五个实体并尝试使用 spring-data-jpa 存储到 h2 数据库,插入到数据库中工作正常,但是在获取具有主键 ID 的对象时,我是得到stackoverflow错误,因为存在循环依赖。

有人可以帮我找出问题所在。

顶级

@Entity
@Table(name = "a")
@Data
public class A{

@Id
@Column(name = "a_id")
private String id;

@Column
private String name;

@Column
private String name2;

@Column
private String name3;

@Column
private String name4;

@Column
private String name5;

@OneToMany(cascade = CascadeType.ALL,mappedBy = "a",fetch = 
FetchType.EAGER)
@JsonManagedReference
private List<B> b;
}

二等舱

@Entity
@Table(name = "b")
@Data
public class B{

@Id
@Column(name = "bname")
private String bname;

@Column
private String bVersion;

@OneToMany(cascade = CascadeType.ALL,mappedBy = "b")
@JsonManagedReference
private List<C> cs;


@ManyToOne
@JoinColumn(name = "a_id")
@JsonBackReference
private A a;
}

三等舱

@Entity
@Data
public class C{

@Id
@Column(name = "cname")
private String cName;


@Column
private String cVersion;

@OneToMany(cascade = CascadeType.ALL,mappedBy = "c")
@JsonManagedReference
private List<D> ds;

@ManyToOne
@JoinColumn(name = "bname")
@JsonBackReference
private B b;
}

四等

@Entity
@Data
public class D{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="d_id")
private long id;

@Column
private String dName;

@Column
private String dName2;


@ElementCollection
@Column
private List<String> dNames;


@OneToMany(cascade = CascadeType.ALL,mappedBy = "d")
@JsonManagedReference
private List<E> e;

@ManyToOne
@JoinColumn(name = "cname")
@JsonBackReference
private C c;

}

Fifth class

@Entity
@Data
public class E{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "e_id")
private long id;

@Column
private String ename;

@Column
private String eName2;


@ManyToOne
@JoinColumn(name = "e_id")
@JsonBackReference
private E e;
}

标签: javahibernatespring-data-jpah2

解决方案


我也遇到了同样的问题,花了一整天的时间。最后,我发现它的问题toString在于 Lombok 使用@Data注解生成的方法。

解决方案:

覆盖、toString方法和编写您自己的实现。如果您不想使用,请toString使用@Getterand@Setter而不是@Data.

为什么

注意:这发生在双向关系中。可以说我有两个实体并且具有双向关系。

@data
Entity1{
  @oneToMany
  public List<Entity2> entity2s;

  //Added by lombok while using @Data
  @Generated
    public String toString() {
        return "entity2s=" + this.getEntity2s() + ")";
    }
}

@data
Entity2{
  @ManytoOne
  public Entity1 entity1;


  //Added by lombok while using @Data
  @Generated
  public String toString() {
    return "entity1=" + this.getEntity1() + ")";
  }

}

toString()在上面的示例中,Entity1 调用Entity2 和toString()Entity2 调用Entity1的 toString()(由 JPA 调用)toString()。这就是循环引用的构建方式。

注:方法同理hashCode

这是一些参考链接,

https://github.com/rzwitserloot/lombok/issues/1007

https://interviewbubble.com/stackoverflow-tostring-method-when-using-lombok/


推荐阅读