实体类循环引用的解决

做orm映射的时候, 因为表之间的各种关系,常常会出现两个实体类之间相互引用。

有三点内容需要考虑,

  1. 相互引用出现在实体类之间 只要不滥用 就不会出现无限递归的情况,当然一不注意也很容易无限递归。
  2. @ManyToOne和@OneToMany在一对关系中同时出现,那么从数据库中查数据也就orm的时候,是不会出现无限递归的,理由和第一条一样只是在两个实体类之间做了循环引用。所以可以推断出,orm框架工作的时候,先把需要的两个数据查出来,然后引用对方,这里是循环引用的问题,并不会无限递归。
  3. 当实体类转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 会直接无限递归程序报错

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值