接着来说这个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>
View Code
如果要解决查询出来实体 将实体转换为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 }
View Code
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 }
View Code
第一种方法:
如上面的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 }
View Code
第二种方法:
如上面的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 }
View Code
声明:
上面的两种方法中 ,分别采用哪个架包中的哪个类,标识的很明白了。
但是由于Spring框架默认的是采用 ...进行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了。