java org.codehaus.jackson.map.JsonMappingException:无限递归(StackOverflowError)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14281541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 15:44:36  来源:igfitidea点击:

org.codehaus.Hymanson.map.JsonMappingException: Infinite recursion (StackOverflowError)

javaweb-serviceshibernate

提问by user1860447

I am trying out some very basic webservice. I get this exception everytime I try to return the Prtnr object.

我正在尝试一些非常基本的网络服务。每次我尝试返回 Prtnr 对象时都会遇到此异常。

Uncaught exception thrown in one of the service methods of the servlet: spitter. Exception thrown : 
org.codehaus.Hymanson.map.JsonMappingException: Infinite recursion (StackOverflowError) 
(through reference chain: org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
...
    at org.codehaus.Hymanson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:164)
    at org.codehaus.Hymanson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    at org.codehaus.Hymanson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
    at org.codehaus.Hymanson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
    ...

The Prtnr class is :

Prtnr 类是:

public class Prtnr implements Cloneable, java.io.Serializable {

    private static final long serialVersionUID = 201207021420600052L;
    private Integer prtnrId;
    private String creatUserId;
    private Date creatTs;
    private String updtUserId;
    private Date updtTs;
    private String prtnrNm;
    private Integer cncilNum;
    private Character prtnrTypCd;
    private Set<PrtnrGeoInfo> prtnrGeoInfos = new HashSet<PrtnrGeoInfo>(0);
    private Set<PrtnrDtl> prtnrDtls = new HashSet<PrtnrDtl>(0);
    private Set<SuplyDtl> suplyDtls = new HashSet<SuplyDtl>(0);
    private Set<TrnsprtDtl> trnsprtDtls = new HashSet<TrnsprtDtl>(0);
    private Set<PrtnrFacil> prtnrFacils = new HashSet<PrtnrFacil>(0);
    private Set<PrtnrHumanResrc> prtnrHumanResrcs = new HashSet<PrtnrHumanResrc>(0);
    .....
    .....
    Getters and setters for these properties
    ...
}

The PrtnrGeoInfo class is :

PrtnrGeoInfo 类是:

public class PrtnrGeoInfo implements java.io.Serializable {
    private PrtnrGeoInfoId id = new PrtnrGeoInfoId();
    private String creatUserId;
    private Date creatTs;
    private String updtUserId;
    private Date updtTs;

    Getters and setters for these properties

}

The PrtnrGeoInfoId class is :

PrtnrGeoInfoId 类是:

public class PrtnrGeoInfoId implements java.io.Serializable {   
    private Prtnr partner;
    private GeoSegment geoSegment;
    private static final long serialVersionUID = 201207060857580050L;

    Getters and setters for these properties
}

I believe it is because of the classes refrencing each other. But how can this problem be resolved. Within the app which is Struts 2 and Spring, this object get passed just fine.

我相信这是因为类相互引用。但是这个问题怎么解决。在 Struts 2 和 Spring 的应用程序中,这个对象被传递得很好。

The controller class is as follows:

控制器类如下:

@Controller
@RequestMapping("/partners")
public class PartnerController {
    @RequestMapping(value="/{id}", method=RequestMethod.GET, headers ={"Accept=text/xml,application/json"})
    @ResponseBody
    public Prtnr getPartner(@PathVariable("id") String id) throws Exception{
        Prtnr partner = null;
        try{
            partner = partnerService.getPartnerById(Integer.valueOf(id));
                System.out.println("******* Test message " );
        }catch(Exception ex){
            System.out.println("******* Exception thrown ... " + ex.getMessage());
        }

        return partner;
    }
}

The calling class is public class TestTemplate {

调用类是 public class TestTemplate {

    private static final long serialVersionUID = 1130201273334264152L;
    public static void main(String[] args){
        Prtnr partner = (Prtnr)new RestTemplate().getForObject("http://localhost:9080/respondersApp/testWs/partners/{id}", Prtnr.class, "1");
        System.out.println("partner name is : " + partner.getPrtnrNm());
    }
}

回答by madx

In this linkyou can find how to solve this.

在此链接中,您可以找到解决此问题的方法。

However below I'll paste the solution in practice.

但是,下面我将在实践中粘贴解决方案。

It's very simple. Assuming that your database query already works without JSON, all you have to do is this:

这很简单。假设您的数据库查询已经在没有 JSON 的情况下工作,您所要做的就是:

Add the @JsonManagedReference In the forward part of the relationship (i.e. User.java class):

@JsonManagedReferenc在关系的前向部分添加e(即User.java类):

@Entity
public class User implements java.io.Serializable{

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private long id;

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

 @ManyToMany
 @JoinTable(name="users_roles",joinColumns=@JoinColumn(name = "user_fk"),
 inverseJoinColumns=@JoinColumn(name = "role_fk"))
 @JsonManagedReference
 private Set<Role> roles = new HashSet<Role>();

...

Add the @JsonBackReferenceIn the back part of the relationship (i.e. Role.java class):

添加@JsonBackReference关系的后面部分(即Role.java类):

@Entity
public class Role implements java.io.Serializable {

 @Id 
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int id;

 @ManyToMany(mappedBy="roles")
 @JsonBackReference
 private Set<User> users = new HashSet<User>();

...

The work is done. If you take a look at your firebug logs, you'll notice that the infinite recursive loop has disappeared.

工作完成了。如果您查看萤火虫日志,您会注意到无限递归循环已经消失。

回答by tarka

This is quite a common scenario for me when you are trying to convert entity classes into JSON format. The simplest solution is just to use @JsonIgnoreon the reverse mapping to break the cycle.

当您尝试将实体类转换为 JSON 格式时,这对我来说是一个很常见的场景。最简单的解决方案就是@JsonIgnore在反向映射上使用来打破循环。

回答by user788052

You can annotate the second reference of Prtnr in PrtnrGeoInfoId with @JsonBackReference

您可以在 PrtnrGeoInfoId 中注释 Prtnr 的第二个引用 @JsonBackReference

回答by hans wurst

this is a general serializing issue. you have to break those dependencies using @Transient while writing to xml or json or object stream.

这是一个一般的序列化问题。在写入 xml 或 json 或对象流时,您必须使用 @Transient 打破这些依赖关系。

and you have to wire them back while reading. wiring is done in such method

你必须在阅读时将它们连接回去。接线是用这种方法完成的

class Way{
list nodes;
addNode(Node node){
node.setWay(this);
nodes.add(node);

}

}

}

回答by Srinivas

The infinite recursion is due to the following: Class Prtnrcontains Set<PrtnrGeoInfo> prtnrGeoInfosand each PrtnrGeoInfocontains PrtnrGeoInfoId idwhich in turn contains Prtnr partner.

无限递归是由于以下原因: Class PrtnrcontainsSet<PrtnrGeoInfo> prtnrGeoInfos和 each PrtnrGeoInfocontains PrtnrGeoInfoId id,而每个contains又包含Prtnr partner.

Thus, Prtnr-> PrtnrGeoInfo->PrtnrGeoInfoId->Prtnr, is causing a cyclic dependency which is a problem for Hymanson when it is trying to do the POJO Mapping.

因此,Prtnr-> PrtnrGeoInfo-> PrtnrGeoInfoId->Prtnr会导致循环依赖,这对于 Hymanson 尝试进行 POJO 映射时是个问题。

You need to remove this cyclic dependency to fix this exception.

您需要删除此循环依赖项以修复此异常。