使用Hibernate框架生成实体类后,经常会将实体类转换为json数据返回给前台页面。但是在转json的过程中由于表之间存在关联关系,由于Hibernate的延迟加载,所以会导致在转json的过程中会出死循环。具体错误如下:
net.sf.json.JSONException: There is a cycle in the hierarchy!
at net.sf.json.util.CycleDetectionStrategy$StrictCycleDetectionStrategy.handleRepeatedReferenceAsObject(CycleDetectionStrategy.java:97)
at net.sf.json.JSONObject._fromBean(JSONObject.java:657)
at net.sf.json.JSONObject.fromObject(JSONObject.java:172)
at net.sf.json.AbstractJSON._processValue(AbstractJSON.java:274)
at net.sf.json.JSONObject._processValue(JSONObject.java:2655)
at net.sf.json.JSONObject.processValue(JSONObject.java:2721)
at net.sf.json.JSONObject.setInternal(JSONObject.java:2736)
at net.sf.json.JSONObject.setValue(JSONObject.java:1424)
at net.sf.json.JSONObject.defaultBeanProcessing(JSONObject.java:765)
at net.sf.json.JSONObject._fromBean(JSONObject.java:699)
at net.sf.json.JSONObject.fromObject(JSONObject.java:172)
at net.sf.json.AbstractJSON._processValue(AbstractJSON.java:274)
at net.sf.json.JSONArray._processValue(JSONArray.java:2513)
at net.sf.json.JSONArray.processValue(JSONArray.java:2538)
at net.sf.json.JSONArray.addValue(JSONArray.java:2525)
............
一般会有如下两种情况会发生上面的错误。
- 页面不需要展示关联数据时
解决:将关联对象属性排除掉
- 页面需要展示关联数据时
解决:将关联对象改为立即加载,并且将关联对象中的属性排除
如下表关系:
学生表和班级表是多对一的关系。
生成的学生表的实体类:
public class Student {
private String id;
private String classId;
private String name;
private Interger gender;
private TClass tclass; //一方
//get、set方法省略
}
学生表的hbm.xml部分:
<many-to-one name="tclass" class="com.test.TClass" fetch="select">
<column name="class_id" length="32" />
</many-to-one>
生成的班级表的实体类:
public class TClass{
private String id;
private String name;
private Set student = new HashSet(0); //多方
}
班级表的hbm.xml部分:
<set name="student" inverse="true">
<key>
<column name="class_id" length="32" />
</key>
<one-to-many class="com.test.Student" />
</set>
当页面上只显示班级信息,不显示关联的学生信息时,
//使用json-lib将TClass对象转为Json,通过输出流写回页面中
JsonConfig jsonConfig = new JsonConfig();
//指定哪些属性不需要转json
jsonConfig.setExcludes(new String[]{"student"});
String json = JSONObject.fromObject(tclass, jsonConfig).toString();
ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
ServletActionContext.getResponse().getWriter().print(json);
当页面上在显示学生信息时,同时还要显示关联的班级信息
//使用json-lib将TClass对象转为Json,通过输出流写回页面中
JsonConfig jsonConfig = new JsonConfig();
//指定哪些属性不需要转json
jsonConfig.setExcludes(new String[]{"student"});
String json = JSONObject.fromObject(tclass, jsonConfig).toString();
ServletActionContext.getResponse().setContentType("text/json;charset=utf-8");
ServletActionContext.getResponse().getWriter().print(json);
修改学生表对应的hbm.xml
<many-to-one lazy="false" name="tclass" class="com.test.TClass" fetch="select">
<column name="class_id" length="32" />
</many-to-one>