我有这样的双向关系...
Person.java
public class Person{
@JsonIgnore
@OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL,
fetch=FetchType.EAGER, mappedBy="person")
private Set<PeopleOrg> organization;
.....
}
PersonOrganization.java
public class PersonOrganization{
@JsonIgnore
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PERSONID", nullable=false)
private Person person;
}
即使使用
@JsonIgnore
注释,我在尝试检索人员记录时也会遇到无限递归错误。我在1.6版本中尝试过新的注释。 @JsonBackReference
和@JsonManagedReference
。即使那样我也会得到无限递归..
将
@JsonBackReference("person-organization")
放在 Person
上并将 @JsonManagedReference("person-organization")
放在 PersonOrganization
上
org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]->com.entity.PersonOrganization["person"]->com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]...
即使我交换注释,我仍然遇到此异常。如果映射或我使用 JSON 注释的方式有问题,请告诉我。谢谢
我以前也遇到过这个问题。但是将 @JsonIgnore 从私有字段移动到字段的 getter 后,无限递归就消失了。所以我的疯狂猜测是 @JsonIgnore 可能在私有领域不起作用。然而,Jackson Java JSON-processor 的 javadoc 或教程没有提到这一点,所以我不能 100% 确定。仅供您参考。
下面的链接说你应该注释JSON工具用来遍历对象图的方法,以指示它忽略遍历。
http://jackson.codehaus.org/1.0.1/javadoc/org/codehaus/jackson/annotate/JsonIgnore.html
就我而言,我有两个相关的对象,例如 Product <-> ProductImage。因此 JSON 解析器进入无限循环,而没有在以下内容上使用 @JsonIgnore 注释来获取方法
@JsonIgnore
public Product getImageOfProduct() {
return imageOfProduct;
}
在产品图片中和
@JsonIgnore
public Set<ProductImage> getProductImages() {
return productImages;
}
在产品中。
有了注释,一切正常。
我知道这个问题并不是专门关于 Spring Data REST 的,但我在 Spring Data REST 的上下文中遇到了这个异常,并且想分享问题是什么。我有一个涉及没有存储库的实体的双向关系。创建存储库使循环消失。
从 Jackson 1.6 开始,您可以使用两个注释来解决无限递归问题,而无需在序列化期间忽略 getter/setter:@JsonManagedReference 和 @JsonBackReference。
有关更多详细信息,请参阅https://stackoverflow.com/a/18288939/286588
显然从 Jackson 1.6 开始,你可以使用 @JsonManagedReference 和 @JsonBackReference 来有效解决无限递归问题。
我不会详细介绍,但是将您的课程更改为以下格式应该可以解决问题。
public class Person{
@OneToMany(targetEntity=PersonOrganization.class, cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="person")
@Column(nullable = true)
@JsonManagedReference
private Set<PeopleOrg> organization;
.....
}
public class PersonOrganization{
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="PERSONID")
@JsonBackReference
private Person person;
}
基本上,Jackson 使用编组过程将引用 a 的前部部分
Set<PeopleOrg> organization
转换为类似 json 的格式,然后查找引用的后部部分 Person person
并且不对其进行序列化。
致谢 - Kurt Bourbaki 及更多信息 - http://keenformatics.blogspot.co.ke/2013/08/how-to-solve-json-infinite-recursion.html
如果 A 有 B,B 有 A。
这是一对一的关系,但是形成了循环关系。
在任何类中,使用 JustIgnore 注释。
class A
{
B b;
}
class B
{
@JsonIgnore
A a;
}
这也适用于其他关系,例如一对多。
这可能有点旧,但您可以在类级别添加 @JsonIgnore 及其应忽略的所有属性。例如
@JsonIgnore("productImaes","...")
public class Product{ ...
}
有时,成员字段可能具有对其自身相同类类型的内部引用,这可能会导致toJson
时的
无限递归。
例如:你有一个成员字段
Klass a
,而该Klass的类定义如下。
class Klass {
Klass mySibling;
public toString() {
return "something" + mySibling.whateverMethod;
}
}
解决方案:重构成员字段,消除内部引用。
这个异常是因为,你的构造函数字段不正确,请再次检查你的类中的构造函数属性,并检查映射是否正确,
保留两个构造函数,第一个是零构造,第二个构造函数带有字段,并且都应该包含 super
对我来说,我尝试过@JsonIgnore,@JsonManagedReference / @JsonBackReference,但没有任何效果,直到我读到此抛出异常[“hibernateLazyInitializer”]解决方案1和此抛出异常[“hibernateLazyInitializer”]解决方案2
解决方案1是从fetch.LAZY改为fetch.EAGER,解决方案2是使用
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
,当然这两个解决方案都使用@JsonIgnore
就我而言,我导入了错误的 @JsonIgnore 注释,例如 net.minidev.json.annotate.JsonIgnore 而不是 com.fasterxml.jackson.annotation.JsonIgnore。更改此导入为我解决了无限递归问题。
Jackson 通过调用 getter 来处理 Reflection。我也遇到过这样的情况,我在其类中有一个相同对象的吸气剂。 Jackson 通过反复调用自己的 getter 来进入无限递归,吞噬堆栈。删除了 getter,然后就修复了。
我的建议: 如果你想使用 jackson 来转换对象,永远不要保留引用同一对象的 getter,就像单例的情况一样。