net.sf.json.JSONException: There is a cycle in the hierarchy!
因为项目中使用了AJAX技术,jar包为:json-lib.jar,在开发过程中遇到了一个JSON-LIB和Hibernate有关的问题:
如hibernate延迟加载错误,这都是些老问题了,一看就知道加个lazy=flase就OK了。想不到快要完成了又遇到了新的问题,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:857) at net.sf.json.JSONObject.fromObject(JSONObject.java:192) at net.sf.json.JSONObject._processValue(JSONObject.java:2774) at net.sf.json.JSONObject._setInternal(JSONObject.java:2798) at net.sf.json.JSONObject.setValue(JSONObject.java:1507) at net.sf.json.JSONObject._fromBean(JSONObject.java:940) at net.sf.json.JSONObject.fromObject(JSONObject.java:192) at net.sf.json.JSONObject._processValue(JSONObject.java:2774) at net.sf.json.JSONObject._setInternal(JSONObject.java:2798) at net.sf.json.JSONObject.setValue(JSONObject.java:1507) at net.sf.json.JSONObject._fromBean(JSONObject.java:940) at net.sf.json.JSONObject.fromObject(JSONObject.java:192) at net.sf.json.JSONObject._processValue(JSONObject.java:2774) at net.sf.json.JSONObject._setInternal(JSONObject.java:2798) at net.sf.json.JSONObject.setValue(JSONObject.java:1507) at net.sf.json.JSONObject._fromBean(JSONObject.java:940) at net.sf.json.JSONObject.fromObject(JSONObject.java:192) at net.sf.json.JSONObject._processValue(JSONObject.java:2774) at net.sf.json.JSONObject._setInternal(JSONObject.java:2798) at net.sf.json.JSONObject.setValue(JSONObject.java:1507) at net.sf.json.JSONObject._fromBean(JSONObject.java:940) at net.sf.json.JSONObject.fromObject(JSONObject.java:192) at net.yanhl.iouser.action.IOUserAction.loadUser(IOUserAction.java:142)
因为Hibernate中设置了自身关联: Iouser.hbm.xml:
<many-to-one name="group" class="net.yanhl.iouser.pojo.GroupRelation" lazy="false" cascade="none">
<column name="group_id"></column>
</many-to-one>
//设置自身关联的组对象
1 public class GroupRelation implements Serializable { 2 3 private static final long serialVersionUID = 6202253180943473205L; 4 5 private Integer id;// 主键ID 6 7 private Integer creatorId;// 创建人 8 9 private Date createDate;// 创建日期 10 11 private String groupName;// 组名称 12 13 private GroupRelation parentGroup; 14 15 private Set<grouprelation> childGroups = new HashSet<grouprelation>(); 16 /******** get set ********/ 17 }
<many-to-one name="parentGroup" column="parent_id" lazy="false" class="net.yanhl.iouser.pojo.GroupRelation"> </many-to-one> <set name="childGroups" cascade="save-update" inverse="true"> <key column="parent_id"></key> <one-to-many class="net.yanhl.iouser.pojo.GroupRelation"></one-to-many> </set>
起初想通过hibernate来解决问题,就是想过滤掉自身关联后来查资料发现不可能实现,最后找到通过JSON-LIB来过滤关联的集合属性。
仔细查了一下发现是hibernate主外键关联的错,后来就想下json源代码下来看,发现大费周章都没搞到json源码,还是老办法反编译瞅瞅,发现JSONArray根据判断取得的不同类型调用相应的方法,
if (object instanceof Collection)
return _fromCollection((Collection)object, jsonConfig);
而我从hibernate那得到的是list,所以去调用了_fromCollection方法,而里面的方法发现一个问题:该方法会不断的拆开实体属性,直到没有为止,而我的GroupRelation里有两个属性用于自身关联
private GroupRelation parentGroup;
private Set<grouprelation> childGroups = new HashSet<grouprelation>();
也就是说主外键自身关联的是个死循环,那怎么才能不让他出现这种情况呢,应该有个配置的参数后者终止循环的地方吧,查看发
现,jsonConfig,呵呵,config应该是配置参数吧,参看JsonConfig看见巨多的属性,有点晕PropertyFilter
,不提了,看了老半天,发现了一个属性PropertyFilter,PropertyFilter 是一个interface,代码如下:
public interface PropertyFilter{
public abstract boolean apply(Object obj, String s, Object obj1);
}
也就是说我可以通过这个方法过滤掉List里的相应属性,只要让它返回true就可过滤掉,我们重写一下这个方法,代码如下:
1 JsonConfig config = new JsonConfig(); 2 3 config.setJsonPropertyFilter(new PropertyFilter(){ 4 5 public boolean apply(Object source, String name, Object value) { 6 7 if(name.equals("parentGroup") || name.equals("childGroups")) { 8 9 return true; 10 11 } else { 12 13 return false; 14 15 } 16 17 } 18 19 }); 20 21 Iouser user = (Iouser) getBaseManager().get(Iouser.class, iouserId); 22 23 JSONObject jsonObject = JSONObject.fromObject(user, config);
将hibernate产生的实体bean中的parentGroup和childGroups过滤掉就OK了!
然后调用JSONArray.fromObject(user,config); user是hibernate返回的list。
当JSON-LIB解析JAVABEAN时过滤掉parentGroup、childGroups这两个属性,重新启动服务,pass
搞了一早上,参考网络的资料!解决问题了!