( 转载 ) @JsonBackReference @JsonManagedReference @JsonIgnore

转自:http://vivus.iteye.com/blog/1613913  作者:vivus

 

jackson中的@JsonBackReference和@JsonManagedReference,以及@JsonIgnore均是为了解决对象中存在双向引用导致的无限递归(infinite recursion)问题。这些标注均可用在属性或对应的get、set方法中。 

@JsonBackReference和@JsonManagedReference:这两个标注通常配对使用,通常用在父子关系中。@JsonBackReference标注的属性在序列化(serialization,即将对象转换为json数据)时,会被忽略(即结果中的json数据不包含该属性的内容)。@JsonManagedReference标注的属性则会被序列化。在序列化时,@JsonBackReference的作用相当于@JsonIgnore,此时可以没有@JsonManagedReference。但在反序列化(deserialization,即json数据转换为对象)时,如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。 

@JsonIgnore:直接忽略某个属性,以断开无限递归,序列化或反序列化均忽略。当然如果标注在get、set方法中,则可以分开控制,序列化对应的是get方法,反序列化对应的是set方法。在父子关系中,当反序列化时,@JsonIgnore不会自动注入被忽略的属性值(父或子),这是它跟@JsonBackReference和@JsonManagedReference最大的区别。 

示例测试代码(注意反序列化后的TreeNode[readValue]的children里的parent): 
TreeNode.java 

Java代码   收藏代码
  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. import org.codehaus.jackson.annotate.JsonBackReference;  
  5. import org.codehaus.jackson.annotate.JsonManagedReference;  
  6.   
  7. public class TreeNode {  
  8.     String name;  
  9.     @JsonBackReference  
  10. //  @JsonIgnore  
  11.     TreeNode parent;  
  12.     @JsonManagedReference  
  13.     List<TreeNode> children;  
  14.   
  15.     public TreeNode() {  
  16.     }  
  17.   
  18.     public TreeNode(String name) {  
  19.         this.name = name;  
  20.     }  
  21.   
  22.     public String getName() {  
  23.         return name;  
  24.     }  
  25.   
  26.     public void setName(String name) {  
  27.         this.name = name;  
  28.     }  
  29.   
  30.     public TreeNode getParent() {  
  31.         return parent;  
  32.     }  
  33.   
  34.     public void setParent(TreeNode parent) {  
  35.         this.parent = parent;  
  36.     }  
  37.   
  38.     public List<TreeNode> getChildren() {  
  39.         return children;  
  40.     }  
  41.   
  42.     public void setChildren(List<TreeNode> children) {  
  43.         this.children = children;  
  44.     }  
  45.   
  46.     public void addChild(TreeNode child) {  
  47.         if (children == null)  
  48.             children = new ArrayList<TreeNode>();  
  49.         children.add(child);  
  50.     }  
  51. }  


JsonTest.java 

Java代码   收藏代码
  1. import java.io.IOException;  
  2.   
  3. import org.codehaus.jackson.JsonGenerationException;  
  4. import org.codehaus.jackson.map.JsonMappingException;  
  5. import org.codehaus.jackson.map.ObjectMapper;  
  6. import org.junit.AfterClass;  
  7. import org.junit.BeforeClass;  
  8. import org.junit.Test;  
  9.   
  10. public class JsonTest {  
  11.     static TreeNode node;  
  12.   
  13.     @BeforeClass  
  14.     public static void setUp() {  
  15.         TreeNode node1 = new TreeNode("node1");  
  16.         TreeNode node2 = new TreeNode("node2");  
  17.         TreeNode node3 = new TreeNode("node3");  
  18.         TreeNode node4 = new TreeNode("node4");  
  19.         TreeNode node5 = new TreeNode("node5");  
  20.         TreeNode node6 = new TreeNode("node6");  
  21.   
  22.         node1.addChild(node2);  
  23.         node2.setParent(node1);  
  24.         node2.addChild(node3);  
  25.         node3.setParent(node2);  
  26.         node2.addChild(node4);  
  27.         node4.setParent(node2);  
  28.         node3.addChild(node5);  
  29.         node5.setParent(node3);  
  30.         node5.addChild(node6);  
  31.         node6.setParent(node5);  
  32.   
  33.         node = node3;  
  34.     }  
  35.   
  36.     @Test  
  37.     public void test() throws JsonGenerationException, JsonMappingException, IOException {  
  38.         ObjectMapper mapper = new ObjectMapper();  
  39.         String json = mapper.writeValueAsString(node);  
  40.         System.out.println(json);  
  41.         TreeNode readValue = mapper.readValue(json, TreeNode.class);  
  42.         System.out.println(readValue.getName());  
  43.     }  
  44.   
  45.     @AfterClass  
  46.     public static void tearDown() {  
  47.         node = null;  
  48.     }  
  49. }  



参考: 
http://wiki.fasterxml.com/JacksonFeatureBiDirReferences 
jira:http://jira.codehaus.org/browse/JACKSON-235 

备注: 
jackson版本:1.9.9 

似乎jackson从2.0开始可以通过@JsonIdentityInfo解决无限递归的问题,但本人没验证。 

有兴趣还可以研究研究这篇文章里的方式: 
http://www.linuxso.com/architecture/26599.html

package com.kucun.data.entity; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonManagedReference; /** 板材 @author Administrator */ @Entity @Table(name=“bancai”) public class Bancai { @Id private int id; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = “caizhi_id”) // @JsonManagedReference // 标记为“主”关联方 private Caizhi caizhi; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JsonBackReference @JoinColumn(name = “mupi1_id”) private Mupi mupi1; @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = “mupi2_id”) @JsonBackReference private Mupi mupi2; private Double houdu; public int getId() { return id; } public void setId(int id) { this.id = id; } public Caizhi getCaizhi() { return caizhi; } public void setCaizhi(Caizhi caizhi) { this.caizhi = caizhi; } public Mupi getMupi1() { return mupi1; } public void setMupi1(Mupi mupi1) { this.mupi1 = mupi1; } public Mupi getMupi2() { return mupi2; } public void setMupi2(Mupi mupi2) { this.mupi2 = mupi2; } public Double getHoudu() { return houdu; } public void setHoudu(Double houdu) { this.houdu = houdu; } @Override public String toString() { return “{id:” + id + “, caizhi:” + caizhi + “, mupi1:” + mupi1 + “, mupi2:” + mupi2 + “, houdu:” + houdu + “}”; } public Bancai(int id, Caizhi caizhi, Mupi mupi1, Mupi mupi2, Double houdu) { super(); this.id = id; this.caizhi = caizhi; this.mupi1 = mupi1; this.mupi2 = mupi2; this.houdu = houdu; } public Bancai() { super(); } } package com.kucun.data.entity; import java.util.List; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; /** 板材材质 @author Administrator */ @Entity @Table(name=“caizhi”) @JsonIgnoreProperties({“hibernateLazyInitializer”, “handler”}) public class Caizhi { @Id private int id ; private String name; @OneToMany(mappedBy=“caizhi”) private List<Bancai> bancais; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return “{id:” + id + “, name:” + name + “}”; } public Caizhi(int id, String name) { super(); this.id = id; this.name = name; } public Caizhi() { super(); } // 添加反向关联维护方法 public void addBancai(Bancai bancai) { bancais.add(bancai); bancai.setCaizhi(this); } // 添加移除方法 public void removeBancai(Bancai bancai) { bancais.remove(bancai); bancai.setCaizhi(null); } } package com.kucun.data.entity; import java.util.List; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.OneToMany; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; /** 木皮 @author Administrator */ @Entity @Table(name=“mupi”) @JsonIgnoreProperties({“hibernateLazyInitializer”, “handler”}) public class Mupi { @Id private int id; private String name; // 添加 OneToMany 映射 @OneToMany(mappedBy = "mupi1") // 指向 Bancai 中的 mupi1 字段 private List<Bancai> bancaisForMupi1; @OneToMany(mappedBy = "mupi2") // 指向 Bancai 中的 mupi2 字段 private List<Bancai> bancaisForMupi2; public Mupi(int id, String name, List<Bancai> bancaisForMupi1, List<Bancai> bancaisForMupi2) { super(); this.id = id; this.name = name; this.bancaisForMupi1 = bancaisForMupi1; this.bancaisForMupi2 = bancaisForMupi2; } public List<Bancai> getBancaisForMupi1() { return bancaisForMupi1; } public void setBancaisForMupi1(List<Bancai> bancaisForMupi1) { this.bancaisForMupi1 = bancaisForMupi1; } public List<Bancai> getBancaisForMupi2() { return bancaisForMupi2; } public void setBancaisForMupi2(List<Bancai> bancaisForMupi2) { this.bancaisForMupi2 = bancaisForMupi2; } @Override public String toString() { return "{id:" + id + ", name:" + name + "}"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Mupi(int id, String name) { super(); this.id = id; this.name = name; } public Mupi() { super(); } } 如何在程序中决定是否连级查找并只查找一级 ,关联的集合中的实体不会再查询它内部的集合,
最新发布
06-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值