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

我正在尝试一些非常基本的Web服务。 每次我尝试返回Prtnr对象时都会收到此exception。

Uncaught exception thrown in one of the service methods of the servlet: spitter. Exception thrown : org.codehaus.jackson.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.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:164) at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446) at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) ... 

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 prtnrGeoInfos = new HashSet(0); private Set prtnrDtls = new HashSet(0); private Set suplyDtls = new HashSet(0); private Set trnsprtDtls = new HashSet(0); private Set prtnrFacils = new HashSet(0); private Set prtnrHumanResrcs = new HashSet(0); ..... ..... Getters and setters for these properties ... } 

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 } 

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 } 

我相信这是因为class级相互重新融合。 但是如何解决这个问题呢。 在Struts 2和Spring的应用程序中,这个对象传递得很好。

控制器类如下:

 @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; } } 

调用类是公共类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()); } } 

在此链接中,您可以找到如何解决此问题。

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

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

添加@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 roles = new HashSet(); ... 

添加@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 users = new HashSet(); ... 

工作完成了。 如果你看一下你的firebug日志,你会发现无限递归循环已经消失了。

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

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

这是一个常见的序列化问题。 在写入xml或json或对象流时,必须使用@Transient来破坏这些依赖项。

你必须在阅读时把它们连接起来。 用这种方法完成布线

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

}

 } 

无限递归是由于以下原因:类Prtnr包含Set prtnrGeoInfos并且每个PrtnrGeoInfo包含PrtnrGeoInfoId id ,而PrtnrGeoInfoId id又包含Prtnr partner

因此, Prtnr – > PrtnrGeoInfo – > PrtnrGeoInfoId – > Prtnr ,导致循环依赖,这对于Jackson试图进行POJO映射是一个问题。

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