我正在尝试一些非常基本的网络服务。每当我尝试返回Prtnr对象时,我都会收到此异常。
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<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
...
}
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
}
我相信这是因为班级互相升华。但是如何解决这个问题呢。在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());
}
}
答案 0 :(得分:6)
在此link中,您可以找到解决此问题的方法。
但是,我将在实践中粘贴解决方案。
这非常简单。假设您的数据库查询在没有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<Role> roles = new HashSet<Role>();
...
在关系的后半部分添加@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>();
...
工作已经完成。如果你看看你的firebug日志,你会注意到无限递归循环已经消失。
答案 1 :(得分:3)
当您尝试将实体类转换为JSON格式时,这是一种非常常见的情况。最简单的解决方案就是在反向映射上使用@JsonIgnore
来打破循环。
答案 2 :(得分:2)
您可以使用@JsonBackReference
答案 3 :(得分:0)
这是一个常见的序列化问题。 你必须在写入xml或json或对象流时使用@Transient来破坏这些依赖关系。
你必须在阅读时将它们连接回来。 用这种方法完成接线
class Way{
list nodes;
addNode(Node node){
node.setWay(this);
nodes.add(node);
}
}
答案 4 :(得分:-1)
无限递归是由于以下原因:
类Prtnr
包含Set<PrtnrGeoInfo> prtnrGeoInfos
,每个PrtnrGeoInfo
包含PrtnrGeoInfoId id
,而Prtnr partner
又包含Prtnr
。
因此,PrtnrGeoInfo
- &gt; PrtnrGeoInfoId
- &gt; Prtnr
- &gt; {{1}}导致循环依赖,这在杰克逊试图进行POJO映射时会出现问题。
您需要删除此循环依赖项以修复此异常。