接着来说这个JSON循环引用的问题:
关于JSON格式的转化,其实关键就是这几个依赖:
1 <!-- json --> 2 3 <!-- 1号 --> 4 <dependency> 5 <groupId>com.fasterxml.jackson.core</groupId> 6 <artifactId>jackson-core</artifactId> 7 <version>2.8.1</version> 8 </dependency> 9 <!-- 2号 --> 10 <dependency> 11 <groupId>com.fasterxml.jackson.core</groupId> 12 <artifactId>jackson-annotations</artifactId> 13 <version>2.8.1</version> 14 </dependency> 15 16 <!-- 3号 --> 17 <dependency> 18 <groupId>com.fasterxml.jackson.core</groupId> 19 <artifactId>jackson-databind</artifactId> 20 <version>2.8.1</version> 21 <exclusions> 22 <exclusion> 23 <artifactId>jackson-core</artifactId> 24 <groupId>com.fasterxml.jackson.core</groupId> 25 </exclusion> 26 <exclusion> 27 <artifactId>jackson-annotations</artifactId> 28 <groupId>com.fasterxml.jackson.core</groupId> 29 </exclusion> 30 </exclusions> 31 </dependency> 32 33 <!-- 4号 --> 34 <dependency> 35 <groupId>com.google.code.gson</groupId> 36 <artifactId>gson</artifactId> 37 <version>2.7</version> 38 </dependency> 39 <!-- 5号 --> 40 <dependency> 41 <groupId>net.sf.json-lib</groupId> 42 <artifactId>json-lib</artifactId> 43 <version>2.4</version> 44 <classifier>jdk15</classifier> 45 </dependency> 46 <!-- 5号json-lib还需要以下依赖包 --> 47 <dependency> 48 <groupId>commons-lang</groupId> 49 <artifactId>commons-lang</artifactId> 50 <version>2.5</version> 51 </dependency> 52 <dependency> 53 <groupId>commons-beanutils</groupId> 54 <artifactId>commons-beanutils</artifactId> 55 <version>1.9.2</version> 56 </dependency> 57 <dependency> 58 <groupId>commons-collections</groupId> 59 <artifactId>commons-collections</artifactId> 60 <version>3.2.1</version> 61 </dependency> 62 <dependency> 63 <groupId>commons-logging</groupId> 64 <artifactId>commons-logging</artifactId> 65 <version>1.2</version> 66 </dependency>
如果要解决查询出来实体 将实体转换为JSON数据的问题,Product产品类:Disease疾病类(1:n)这两个实体类正确写法如下:
Product.java
1 package com.agen.entity; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.CascadeType; 7 import javax.persistence.Column; 8 import javax.persistence.Entity; 9 import javax.persistence.FetchType; 10 import javax.persistence.GeneratedValue; 11 import javax.persistence.Id; 12 import javax.persistence.OneToMany; 13 import javax.persistence.Table; 14 import javax.persistence.Transient; 15 16 import org.hibernate.annotations.GenericGenerator; 17 18 import com.fasterxml.jackson.annotation.JsonIgnore; 19 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 20 import com.google.gson.annotations.Expose; 21 22 /** 23 * Product entity. @author MyEclipse Persistence Tools 24 */ 25 @Entity 26 @Table(name = "product", catalog = "biologyinfo") 27 28 public class Product implements java.io.Serializable { 29 30 private static final long serialVersionUID = 1L; 31 private String productId; 32 private String productName; 33 private String productPath; 34 private Integer productOrder; 35 private String productCre; 36 private Set<Disease> diseases = new HashSet<Disease>(0); 37 38 // Constructors 39 40 /** default constructor */ 41 public Product() { 42 } 43 44 /** full constructor */ 45 public Product(String productName, String productPath, 46 Integer productOrder, String productCre, Set<Disease> diseases) { 47 this.productName = productName; 48 this.productPath = productPath; 49 this.productOrder = productOrder; 50 this.productCre = productCre; 51 this.diseases = diseases; 52 } 53 54 // Property accessors 55 @GenericGenerator(name = "generator", strategy = "uuid.hex") 56 @Id 57 @GeneratedValue(generator = "generator") 58 @Column(name = "productId", unique = true, nullable = false, length = 36) 59 public String getProductId() { 60 return this.productId; 61 } 62 63 public void setProductId(String productId) { 64 this.productId = productId; 65 } 66 67 @Column(name = "productName", length = 30) 68 public String getProductName() { 69 return this.productName; 70 } 71 72 public void setProductName(String productName) { 73 this.productName = productName; 74 } 75 76 @Column(name = "productPath", length = 200) 77 public String getProductPath() { 78 return this.productPath; 79 } 80 81 public void setProductPath(String productPath) { 82 this.productPath = productPath; 83 } 84 85 @Column(name = "productOrder") 86 public Integer getProductOrder() { 87 return this.productOrder; 88 } 89 90 public void setProductOrder(Integer productOrder) { 91 this.productOrder = productOrder; 92 } 93 94 @Column(name = "productCre", length = 500) 95 public String getProductCre() { 96 return this.productCre; 97 } 98 99 public void setProductCre(String productCre) { 100 this.productCre = productCre; 101 } 102 103 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "product") 104 public Set<Disease> getDiseases() { 105 return this.diseases; 106 } 107 108 public void setDiseases(Set<Disease> diseases) { 109 this.diseases = diseases; 110 } 111 112 113 }
Disease.java
1 package com.agen.entity; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.CascadeType; 7 import javax.persistence.Column; 8 import javax.persistence.Entity; 9 import javax.persistence.FetchType; 10 import javax.persistence.GeneratedValue; 11 import javax.persistence.Id; 12 import javax.persistence.JoinColumn; 13 import javax.persistence.ManyToOne; 14 import javax.persistence.OneToMany; 15 import javax.persistence.Table; 16 17 import org.hibernate.annotations.GenericGenerator; 18 19 import com.fasterxml.jackson.annotation.JsonIgnore; 20 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 21 import com.google.gson.annotations.Expose; 22 23 /** 24 * Disease entity. @author MyEclipse Persistence Tools 25 */ 26 @Entity 27 @Table(name = "disease", catalog = "biologyinfo") 28 @JsonIgnoreProperties(value = {"product"}) 29 public class Disease implements java.io.Serializable { 30 31 32 /** 33 * 34 */ 35 private static final long serialVersionUID = 1L; 36 private String diseaseId; 37 private transient Product product; 38 private String diseaseName; 39 private String diseasePath; 40 private Integer diseaseOrder; 41 private String diseaseCre; 42 private Set<Filelist> filelists = new HashSet<Filelist>(0); 43 private Set<Gene> genes = new HashSet<Gene>(0); 44 45 // Constructors 46 47 /** default constructor */ 48 public Disease() { 49 } 50 51 /** minimal constructor */ 52 public Disease(Product product) { 53 this.product = product; 54 } 55 56 /** full constructor */ 57 public Disease(Product product, String diseaseName, String diseasePath, 58 Integer diseaseOrder, String diseaseCre, Set<Filelist> filelists, 59 Set<Gene> genes) { 60 this.product = product; 61 this.diseaseName = diseaseName; 62 this.diseasePath = diseasePath; 63 this.diseaseOrder = diseaseOrder; 64 this.diseaseCre = diseaseCre; 65 this.filelists = filelists; 66 this.genes = genes; 67 } 68 69 // Property accessors 70 @GenericGenerator(name = "generator", strategy = "uuid.hex") 71 @Id 72 @GeneratedValue(generator = "generator") 73 @Column(name = "diseaseId", unique = true, nullable = false, length = 36) 74 public String getDiseaseId() { 75 return this.diseaseId; 76 } 77 78 public void setDiseaseId(String diseaseId) { 79 this.diseaseId = diseaseId; 80 } 81 82 @ManyToOne(fetch = FetchType.LAZY) 83 @JoinColumn(name = "productId", nullable = false) 84 public Product getProduct() { 85 return this.product; 86 } 87 88 public void setProduct(Product product) { 89 this.product = product; 90 } 91 92 @Column(name = "diseaseName", length = 30) 93 public String getDiseaseName() { 94 return this.diseaseName; 95 } 96 97 public void setDiseaseName(String diseaseName) { 98 this.diseaseName = diseaseName; 99 } 100 101 @Column(name = "diseasePath", length = 200) 102 public String getDiseasePath() { 103 return this.diseasePath; 104 } 105 106 public void setDiseasePath(String diseasePath) { 107 this.diseasePath = diseasePath; 108 } 109 110 @Column(name = "diseaseOrder") 111 public Integer getDiseaseOrder() { 112 return this.diseaseOrder; 113 } 114 115 public void setDiseaseOrder(Integer diseaseOrder) { 116 this.diseaseOrder = diseaseOrder; 117 } 118 119 @Column(name = "diseaseCre", length = 500) 120 public String getDiseaseCre() { 121 return this.diseaseCre; 122 } 123 124 public void setDiseaseCre(String diseaseCre) { 125 this.diseaseCre = diseaseCre; 126 } 127 128 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "disease") 129 public Set<Filelist> getFilelists() { 130 return this.filelists; 131 } 132 133 public void setFilelists(Set<Filelist> filelists) { 134 this.filelists = filelists; 135 } 136 137 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "disease") 138 public Set<Gene> getGenes() { 139 return this.genes; 140 } 141 142 public void setGenes(Set<Gene> genes) { 143 this.genes = genes; 144 } 145 146 }
第一种方法:
如上面的Disease.java实体类的类上添加了@JsonIgnoreProperties(value = {"product"})
这个表明 ,现在是在Disease对象的product字段上进行循环引用的隔断。
那么查询的时候,查询Product实体,其中的的disease这个字段是有值的;但是查询Disease实体,其中的product字段是没有值的,因为这个注解在Disease.java类上进行的注解。
同理,如果将这个注解加在哪个实体上,指定了哪个字段就是在哪个字段上阻断。
那么此时的Controller中,我要查询Product对象,并且要将查询出来的对象转化为JSON格式的数据:
1 @RequestMapping("/disease") 2 public String checkdisease(String productId, ModelMap model) 3 throws IOException { 4 Product product = productService.get(productId); 5 //将对象转化为JSON字符串 6 //方法1 com.fasterxml.jackson.databind.ObjectMapper 使用3号架包 7 ObjectMapper mapper = new ObjectMapper(); 8 String json = mapper.writeValueAsString(product); 9 model.addAttribute("product", json); 10 11 //将JSON字符串 转化为对象[只是在此将方法列出,并无实际意义] 12 //com.fasterxml.jackson.databind.ObjectMapper 使用3号架包 13 Product product2 = mapper.readValue(json, Product.class); 14 15 return "/geneinfo/disease/disease"; 16 }
第二种方法:
如上面的Disease.java实体类上添加了Java的关键字 transient
使用transient关键字的作用在于:变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问
这个也是阻断循环引用的一种方法。
同样的,查询Product实体,其中的的disease这个字段是有值的;但是查询Disease实体,其中的product字段是没有值的,因为这个关键字在Disease.java类的product字段上加的。
同理,将这个关键字加在那个字段上 就是在哪个字段上阻断。
那么 此时的Controller中,我们要查询Product对象,并且要将查询出来的对象转化为JSON格式的数据:
1 @RequestMapping("/disease") 2 public String checkdisease(String productId, ModelMap model) 3 throws IOException { 4 Product product = productService.get(productId); 5 //将对象转化为JSON字符串 6 //方法1 com.google.gson.Gson 使用4号架包 7 String json1 = new Gson().toJson(product); 8 model.addAttribute("product", json1); 9 return "/geneinfo/disease/disease"; 10 }
声明:
上面的两种方法中 ,分别采用哪个架包中的哪个类,标识的很明白了。
但是由于Spring框架默认的是采用 com.fasterxml.jackson.annotation进行JSON的转化,所以我们第一种方法中的@JsonIgnoreProperties(value = {"product"})注解必须要添加在实体上。
第二种中的transient关键字是和采用com.google.gson.Gson 谷歌提供的这个架包中的方法配套使用,如果不使用第二种方法进行对象转化JSON格式的数据,可以不用在字段上添加关键字。
声明2:
//net.sf.json.JSONObject
JSONObject.fromObject(product2).toString();
这种将Object转化为JSON数据的方法比较常见,但是它这个架包识别不到@JsonIgnoreProperties这个注解,因为他们不是同一个架包,不是同一个规范,所以在转化JSON的时候,会发生循环引用的问题。
因此这里不采用这种方式转化!!!
一个学习关键字transient的好文章 给大家推荐:http://www.cnblogs.com/lanxuezaipiao/p/3369962.html
当然使用了这两种的方法之后,就不用采用@JsonIgnore了。