无法编写JSON:无限递归(StackOverflowError); 嵌套异常弹簧启动

Bik*_*hal 6 recursion spring json hibernate spring-boot

这是我的区域控制器,当我尝试获取数据后保存我得到错误,即使我尝试获取对象形式getDistrict(长id)同样的罢工请建议一些方式,我是非常新的春天环境

    package com.gad.services;

    import java.util.List;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import com.gad.repositories.DistrictMasterRepositories;
    import com.gad.rmodels.Districtmaster;
    import com.gad.rmodels.Statemaster;

    @Service
    public class DistricMasterServices {

        @Autowired
        DistrictMasterRepositories districtMasterRepositories;
        @Autowired
        StateMasterServices stateMasterServices;
        List<Districtmaster> districtmaster;

        public Iterable<Districtmaster> savenewdistrict(Long id,Districtmaster districtmaster_rec){
             System.out.println(id);
             Statemaster statemaster=null;
             statemaster = stateMasterServices.getStateById(id);
             System.out.println("savenewdistrict");



                districtmaster_rec.setStatemaster(statemaster);
                districtMasterRepositories.save(districtmaster_rec);
                    Iterable<Districtmaster>districtmaster2 = districtMasterRepositories.findAll();
                    return  districtmaster2;


        }


        public Districtmaster  getDistrict(Long id){
            Districtmaster districtmaster =  districtMasterRepositories.findOne(id);
            return districtmaster;

        }
    }
Run Code Online (Sandbox Code Playgroud)

状态的模型类

 package com.gad.rmodels;
    import static javax.persistence.GenerationType.SEQUENCE;
    import java.util.HashSet;
    import java.util.Set;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.SequenceGenerator;
    import javax.persistence.Table;

    /**
     * Statemaster generated by hbm2java
     */
    @Entity
    @Table(name="statemaster"
        ,schema="aop_gad_v1"
    )
    public class Statemaster  implements java.io.Serializable {


         private long id;
         private String stateName;
         private Set<Districtmaster> districtmasters = new HashSet<Districtmaster>(0);

        public Statemaster() {
        }


        public Statemaster(long id) {
            this.id = id;
        }
        public Statemaster(long id, String stateName, Set<Districtmaster> districtmasters) {
           this.id = id;
           this.stateName = stateName;
           this.districtmasters = districtmasters;
        }



        @SequenceGenerator(name="generator_statemasterid", sequenceName="aop_gad_v1.gad_statemaster_seq")
        @Id 
        @GeneratedValue(strategy=SEQUENCE, generator="generator_statemasterid")
        @Column(name="id", unique=true, nullable=false)
        public long getId() {
            return this.id;
        }

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

        @Column(name="state_name", length=20)
        public String getStateName() {
            return this.stateName;
        }

        public void setStateName(String stateName) {
            this.stateName = stateName;
        }

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
        public Set<Districtmaster> getDistrictmasters() {
            return this.districtmasters;
        }

        public void setDistrictmasters(Set<Districtmaster> districtmasters) {
            this.districtmasters = districtmasters;
        }




    }
Run Code Online (Sandbox Code Playgroud)

分区模型

package com.gad.rmodels;


import static javax.persistence.GenerationType.SEQUENCE;

import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

/**
 * Districtmaster generated by hbm2java
 */
@SuppressWarnings("serial")
@Entity
@Table(name="districtmaster",schema="aop_gad_v1")
public class Districtmaster  implements java.io.Serializable {


     private long id;
     private Statemaster statemaster;
     private String districtName;
     private Set<GadGuestHouseMaster> gadGuestHouseMasters = new HashSet<GadGuestHouseMaster>(0);

    public Districtmaster() {
    }


    public Districtmaster(long id) {
        this.id = id;
    }
    public Districtmaster(long id, Statemaster statemaster, String districtName, Set<GadGuestHouseMaster> gadGuestHouseMasters) {
       this.id = id;
       this.statemaster = statemaster;
       this.districtName = districtName;
       this.gadGuestHouseMasters = gadGuestHouseMasters;
    }


     @SequenceGenerator(name="generator_districtmasterid", sequenceName="aop_gad_v1.gad_districtmasterid_seq")
     @Id 
     @GeneratedValue(strategy=SEQUENCE, generator="generator_districtmasterid")
     @Column(name="id", unique=true, nullable=false)
    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }
@ManyToOne(fetch=FetchType.LAZY)

    @JoinColumn(name="district_of_state")
    public Statemaster getStatemaster() {
        return this.statemaster;
    }

    public void setStatemaster(Statemaster statemaster) {
        this.statemaster = statemaster;
    }

    @Column(name="district_name", length=20)
    public String getDistrictName() {
        return this.districtName;
    }

    public void setDistrictName(String districtName) {
        this.districtName = districtName;
    }
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="districtmaster")
    public Set<GadGuestHouseMaster> getGadGuestHouseMasters() {
        return this.gadGuestHouseMasters;
    }

    public void setGadGuestHouseMasters(Set<GadGuestHouseMaster> gadGuestHouseMasters) {
        this.gadGuestHouseMasters = gadGuestHouseMasters;
    }




}
Run Code Online (Sandbox Code Playgroud)

我得到的错误

[{"timestamp":1512641978311,"status":200,"error":"OK","exception":"org.springframework.http.converter.HttpMessageNotWritableException","message":"无法写入JSON:无限递归(StackOverflowError);嵌套异常是com.fasterxml.jackson.databind.JsonMappingException:无限递归(StackOverflowError)(通过引用链:com.gad.rmodels.Statemaster [\"districtmasters \"] - > org.hibernate.collection.internal .PersistentSet [0] -

小智 23

您正面临这个问题,因为Statemaster模型包含区域主模型的对象,该模型本身包含Statemaster模型的对象.这会导致无限的json递归.

您可以通过3种方法解决此问题.

1 - 创建DTO并仅包括要在响应中显示的字段.

2 - 您可以使用@JsonManagedReference@JsonBackReference注释.

例如,将@JsonManagedReference注释添加到Statemaster模型.

@JsonManagedReference
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
    return this.districtmasters;
}
Run Code Online (Sandbox Code Playgroud)

@JsonBackReference注释添加到区域主管模型.

@JsonBackReference
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="district_of_state")
public Statemaster getStatemaster() {
    return this.statemaster;
}
Run Code Online (Sandbox Code Playgroud)

3 - 您可以@JsonIgnore在getter或setter方法上使用注释.

@JsonIgnore
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="statemaster")
public Set<Districtmaster> getDistrictmasters() {
    return this.districtmasters;
}
Run Code Online (Sandbox Code Playgroud)

但是,这种方法会从响应中省略一组区域管理员.


小智 12

@JsonBackReference@JsonManagedReference对我不起作用,因为我使用的是表示联接表的类,而使其工作的唯一方法是将 @JsonBackReference 放在表示链接类的字段之上。最终效果是,如果我使用 JSON 从连接类中提取记录,则不会显示任何连接字段,从而使返回的信息无用。

我会举一些例子,但我喜欢避免冗长的回复。下面文章中解释的@JsonIdentityInfo提供了一个简短但高效的解决方案。

解决方案预览

双向关系和无限递归


Ser*_*hak 7

那是因为在 json 中放置了 的集合StatemasterDistrictmaster而且每个Districtmaster都有它Statemaster自己,所以它也被放入json中。这样你就得到了无限递归

    @JsonIgnore
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, 
    mappedBy="statemaster")
    public Set<Districtmaster> getDistrictmasters() {
        return this.districtmasters;
    }
Run Code Online (Sandbox Code Playgroud)

添加@JsonIgnore注释Set<Districtmaster>将阻止该递归。您可以将其放在任一@JsonIgnore位置public Statemaster getStatemaster()

  • 如果我放置“@JsonIgnore”,那么我不会获得关联的实体数据。如何解决这个问题? (4认同)

Ris*_*wal 6

处理双向映射时会出现此问题。在 DAO/实体类中使用@JsonManagedReferencand@JsonBackReference

\n

@JsonManagedReference是引用 \xe2\x80\x93 的前部,正常序列化的部分。\n@JsonBackReference是引用 \xe2\x80\x93 的后部,它将在序列化中被省略。

\n

(阅读更多)

\n


Fao*_*uzi 5

几天来,我一直在同一个问题上挣扎,我尝试了@ JsonIgnore,@ JsonManagedReference和@JsonBackReference注释,甚至@JsonIdentityInfo注释,但它们都没有起作用。

如果您(将来的读者)处于相同的情况,则解决方案比您预期的要容易,只需将@JsonIgnore或@JsonManagedReference / @JsonBackReference 放在属性的getter上,而不是放在属性本身上。这样就可以了。

这是一个简单的示例:

假设我们有两个类,即Order和Product,以及它们之间的OneToMany关系。

订单类别

public class Order{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_order;
  private double price;
  @OneToMany(mappedBy = "order")
  @LazyCollection(LazyCollectionOption.FALSE)
  private List<Product> products
  //constructor, getters & setter 
}
Run Code Online (Sandbox Code Playgroud)

产品类别:

public class Product{
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private String id_product;
   private String name;
   @ManyToOne
   @JoinColumn(name = "id_order")
   private Order order;
   //consturctor, getters & setters
 }
Run Code Online (Sandbox Code Playgroud)

因此,为了使用@JsonManagedReference和@JsonBackReference,只需将它们添加到getter中,如下所示:

public class Order{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_order;
  private double price;
  @OneToMany(mappedBy = "order")
  @LazyCollection(LazyCollectionOption.FALSE)
  private List<Product> products
  //constructor, getters & setter 
  @JsonManagedReference
  public List<Product> getProducts(){
    return products;
}
Run Code Online (Sandbox Code Playgroud)

产品类别:

public class Product{
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private String id_product;
  private String name;
  @ManyToOne
  @JoinColumn(name = "id_order")
  private Order order;
  //consturctor, getters & setters
  @JsonBackReference
  public Order getOrder(){
    return order;
  }
 }
Run Code Online (Sandbox Code Playgroud)

  • 我正在使用 lombok,那么我该如何使用这个解决方案呢? (3认同)
  • 对于所有想知道如何将其与 Lombok 结合起来的人:只需为相关字段提供一个遵循 JavaBean 命名约定的显式 getter,并将注释放在显式方法之上即可。 (3认同)
  • 如果你使用龙目岛怎么办?如何将 @JsonManagedReference 放在 getter 方法上? (2认同)