Hibernate OneToMany java.lang.StackOverflowError

二次信任 提交于 2019-12-03 01:04:36

The only way it can throw an StackOverFlow is when your Team's League is accessed recursively....

Team to League to Team to League

I'm guessing there's some function trying to convert your objects into some other representation reflectively or recursively resulting in an infinite loop.

I had a very similar issue. I was using Lombok's @Data annotation on my model objects to auto-generate getters, setters, and other standard methods. I believe the toString() method generated by Lombok introduced a circular dependency between my Team and League objects. When I tried to get the Set<teams> teams from my League object, I got a java.lang.StackOverflowError because Spring was calling the toString method for logging purposes.

I resolved this by getting rid of Lombok's toString() method. I replaced the @Data annotation with Lombok's @Getter and @Setter annotations. That way I still could benefit from free getters and setters without getting the toString() method.

Circular dependency can originate from Lombok's toString() autogenerated method, if you use @Data complex annotation. To exclude your circular dependecy for a certain field:

@Entity
@Data
public class Team {

  ...

  @ToString.Exclude
  @ManyToOne
  private League league;
}

For me, Both hashCode and toString default implementation provided by Lombok was causing this issue.

You can use this annotation to exclude members for both equalsAndHasCode with single annotation:

@EqualsAndHashCode(exclude = {"certificates", "payment"})

Also if you want to exclude just members from equals method, Lombok provide : @ToString.Exclude

@ToString.Exclude
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "shipment")
    private Set<Certificate> certificates;

I had similar issue and in my case nothing of this didnt help.

Helped this one approach:

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "order_id")
@Fetch(value = FetchMode.SUBSELECT)
private List<Product> orderLines; 

name = "order_id" is a foreign key column from Product table.

And i didnt put anything in Product entity.

I had this error because I was parsing a list of objects mapped on both sides @OneToMany and @ManyToOne to json using jackson which caused an infinite loop.

If you are in the same situation you can solve this by using @JsonManagedReference and @JsonBackReference annotations.

Definitions from API :

  • JsonManagedReference (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html) :

    Annotation used to indicate that annotated property is part of two-way linkage between fields; and that its role is "parent" (or "forward") link. Value type (class) of property must have a single compatible property annotated with JsonBackReference. Linkage is handled such that the property annotated with this annotation is handled normally (serialized normally, no special handling for deserialization); it is the matching back reference that requires special handling

  • JsonBackReference: (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html):

    Annotation used to indicate that associated property is part of two-way linkage between fields; and that its role is "child" (or "back") link. Value type of the property must be a bean: it can not be a Collection, Map, Array or enumeration. Linkage is handled such that the property annotated with this annotation is not serialized; and during deserialization, its value is set to instance that has the "managed" (forward) link.

Example:

Owner.java:

@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;

Car.java:

@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;

Another solution is to use @JsonIgnore which will just set null to the field.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!