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

搞了一早上,参考网络的资料!解决问题了!

你可能感兴趣的:(exception)