做orm映射的时候, 因为表之间的各种关系,常常会出现两个实体类之间相互引用。
有三点内容需要考虑,
- 相互引用出现在实体类之间 只要不滥用 就不会出现无限递归的情况,当然一不注意也很容易无限递归。
- @ManyToOne和@OneToMany在一对关系中同时出现,那么从数据库中查数据也就orm的时候,是不会出现无限递归的,理由和第一条一样只是在两个实体类之间做了循环引用。所以可以推断出,orm框架工作的时候,先把需要的两个数据查出来,然后引用对方,这里是循环引用的问题,并不会无限递归。
- 当实体类转JSON时,也就是序列化的时候,由于相互引用 这个序列化就会出现无限递归。此时我们需要使用@JsonBackReference注解断开无限递归,它的作用是序列化的时候忽略被注解属性。对反序列化没有影响。而另一个@JsonManagedReference注解是反序列化时工作,当反序列化时,如果JSON字符串没有提供对应的属性(一般就是因为被@JsonBackReference忽略了) 那么@JsonManagedRefercen注解的属性 就会把被@JsonBackReference自动注入进去。
说起来实在太抽象了,其实非常简单,直接上代码。
import com.fasterxml.jackson.annotation.JsonManagedReference;
public class Parent {
String name;
@JsonManagedReference
Son son;
public Parent(){}
public Parent(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Son getSon() {
return son;
}
public void setSon(Son son) {
this.son = son;
}
@Override
public String toString() {
if(son == null)
return name+":null";
return name+":"+son.getName();
}
}
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class Son {
String name;
//@JsonIgnore
@JsonBackReference
Parent parent;
public Son(){}
public Son(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public String toString() {
if(parent == null)
return name+":null";
return name+":"+parent.getName();
}
}
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class TestJackson {
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
Parent p = new Parent("p1");
Son s = new Son("s1");
s.setParent(p);
p.setSon(s);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(p); //Parent序列化
System.out.println(json);
Parent parent = mapper.readValue(json, Parent.class);//Parent反序列化
System.out.print(parent.getName()+" ");
System.out.println(parent.getSon());
json = mapper.writeValueAsString(s); //Son序列化
System.out.println(json);
json = "{\"name\":\"s1\", \"parent\":{\"name\":\"p1\",\"son\":{\"name\":\"s1\"}}}";
Son son = mapper.readValue(json, Son.class); //Son反序列化
System.out.println(son);
}
}
Output:
{"name":"p1","son":{"name":"s1"}}
p1 s1:p1
{"name":"s1"}
s1:p1
注释掉//json = "{\"name\":\"s1\", \"parent\":{\"name\":\"p1\",\"son\":{\"name\":\"s1\"}}}";
也就是序列化 {"name":"s1"}的输出如下:
{"name":"p1","son":{"name":"s1"}}
p1 s1:p1
{"name":"s1"}
s1:null
注释掉//@JsonManagedReference
那么 反序列化 {"name":"p1","son":{"name":"s1"}}就不会把p1自动注入到son里面去
{"name":"p1","son":{"name":"s1"}}
p1 s1:null
{"name":"s1"}
s1:p1
当然 如果不用@JsonBackReference 会直接无限递归程序报错