[org.springframework.http.converter.HttpMessageNotWritableException:无法写入JSON:无限递归(StackOverflowError);

问题描述 投票:0回答:1

我有两个实体类:Country 和 State,它们具有以下关系。尽管我已在 State 实体中将 Country 标记为惰性,但它仍在尝试获取它,并且我收到了 Country 和 State 的无限 JSON 响应,从而导致无限递归 (StackOverflowError)。我知道我可以通过在 Country 类中的 State 之上使用 @JsonIgnore 来解决这个问题。但为什么状态被标记为 (fetch = FetchType.LAZY) 后仍会被获取?

package com.bezkoder.springjwt.models;

import javax.persistence.*;
import java.util.List;

@Entity
public class Country {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "country", cascade = CascadeType.ALL)
    //@JsonIgnore
    private List<State> states;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<State> getStates() {
        return states;
    }

    public void setStates(List<State> states) {
        this.states = states;
    }

    @Override
    public String toString() {
        return "Country{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

状态.java

package com.bezkoder.springjwt.models;

import javax.persistence.*;
import java.util.List;

@Entity
public class State {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id")
    private Country country;

    @OneToMany(mappedBy = "state", cascade = CascadeType.ALL)
    private List<City> cities;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Country getCountry() {
        return country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }

    public List<City> getCities() {
        return cities;
    }

    public void setCities(List<City> cities) {
        this.cities = cities;
    }
    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        return id != null && id.equals(((State) obj).id);
    }

    @Override
    public int hashCode() {
        return 2021;
    }
    @Override
    public String toString() {
        return "State{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

异常

Hibernate: select country0_.id as id1_1_, country0_.name as name2_1_ from country country0_
Hibernate: select states0_.country_id as country_3_10_0_, states0_.id as id1_10_0_, states0_.id as id1_10_1_, states0_.country_id as country_3_10_1_, states0_.name as name2_10_1_ from state states0_ where states0_.country_id=?
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at open/src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 873
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message transform method call failed at open/src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 873
2024-03-16 17:54:22.052  WARN 31312 --- [nio-8771-exec-1] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]->com.bezkoder.springjwt.models.State["country"]->com.bezkoder.springjwt.models.Country["states"]->org.hibernate.collection.internal.PersistentBag[0]-
java spring hibernate jpa
1个回答
0
投票

当您发送响应时,jakson 将尝试检索属性,包括 FetchType 设置为“LAZY”的属性。我假设您使用的是 Spring Boot,在这种情况下,您可能将 open-in-view 选项设置为“True”(默认值),因此存在出现问题 N+1 的风险。

要解决这个问题,您可以创建响应对象(DTO),或使用注释
Country.states 上的

JsonManagedReference
State.country 上的
JsonBackReference

© www.soinside.com 2019 - 2024. All rights reserved.