• 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

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

  • 相关阅读:
    用 Web 实现一个简易的音频编辑器
    TypeScript教程
    他的独,殇情沉醉
    重新拎一遍js的正则表达式
    网络流
    Xmind最新的安装与破解教程
    adb的端口号5037被占用的解决方法
    使用Fiddler模拟弱网测试教程
    web的前台、后台、前端、后端
    常见面试笔试题
  • 原文地址:https://www.cnblogs.com/xinzehome/p/3722843.html
Copyright © 2020-2023  润新知