将具有关联关系的两个表通过hibernate从数据库中查出来后转成Json对象时报错解决 - Go语言中文社区

将具有关联关系的两个表通过hibernate从数据库中查出来后转成Json对象时报错解决


第一篇文章:

相信大家做过JSON相关的东西对这个异常并不陌生,这个异常是由于JSONObject插件内部会无限拆解你传入的对象,直到没有可拆解为止,问题就在这,如果你传入的对象有外键关系,或者相互引用,那么内部就会死循环,也就会抛出这个异常
解决办法,我们先说一种网上通用的:过滤
     不错,过滤肯定会解决该问题,过滤也有两种方法:

     一种是通过

Java代码   收藏代码
  1. jsonConfig.setExcludes(new String[]{"dianYuanHeSuans"})  
 

    该方法接受一个数组,也就是你需要过滤的字段,很简单就能完成。
     二种是通过

Java代码   收藏代码
  1. jsonConfig.setJsonPropertyFilter(new PropertyFilter() {  
  2.               
  3.             @Override  
  4.             public boolean apply(Object source, String name, Object value) {  
  5.                 if(name.equals("qualityChecks")){  
  6.                     return true;  
  7.                 }  
  8.                 return false;  
  9.             }  
  10.         });  
 

这种方式,其实和第一种差不多,达到同样的效果,也很简单。

接下来是我主要想说的,其实这两种方法,有种弊端

假如说我们一个User对象里有个属性是部门,引用的是Organzition这个对象,如果不做任何处理,调用JSONObject.fromObject方法同样会抛出异常,如果我们通过过滤把Organzition属性过滤了,那么在前台显示的时候,将看不到有关部门的任何信息,其实需要显示也不多,比如仅一个部门名字就可以,但是过滤掉什么都没有了,这个时候,很多同学会再建一个VO类来封装前台需要的属性,这无疑增加了工作量和代码的冗余,LZ正是被该问困扰了很久,所以给出个解决办法。

 

借用JSONObject里的JsonValueProcessor接口,我们自己实现该接口,代码如下:

Java代码   收藏代码
  1. /** 
  2.  * 解决JSONObject.fromObject抛出"There is a cycle in the hierarchy"异常导致死循环的解决办法 
  3.  * @author LuoYu 
  4.  * @date 2012-11-23 
  5.  */  
  6. public class ObjectJsonValueProcessor implements JsonValueProcessor {  
  7.       
  8.     /** 
  9.      * 需要留下的字段数组 
  10.      */  
  11.     private String[] properties;  
  12.       
  13.     /** 
  14.      * 需要做处理的复杂属性类型 
  15.      */  
  16.     private Class<?> clazz;  
  17.       
  18.     /** 
  19.      * 构造方法,参数必须 
  20.      * @param properties 
  21.      * @param clazz 
  22.      */  
  23.     public ObjectJsonValueProcessor(String[] properties,Class<?> clazz){  
  24.         this.properties = properties;  
  25.         this.clazz =clazz;  
  26.     }  
  27.   
  28.     @Override  
  29.     public Object processArrayValue(Object value, JsonConfig jsonConfig) {  
  30.         return "";  
  31.     }  
  32.   
  33.     @Override  
  34.     public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {  
  35.         PropertyDescriptor pd = null;  
  36.         Method method = null;  
  37.         StringBuffer json = new StringBuffer("{");  
  38.         try{  
  39.             for(int i=0;i<properties.length;i++){  
  40.                 pd = new PropertyDescriptor(properties[i], clazz);  
  41.                 method = pd.getReadMethod();  
  42.                 String v = String.valueOf(method.invoke(value));  
  43.                 json.append("'"+properties[i]+"':'"+v+"'");  
  44.                 json.append(i != properties.length-1?",":"");  
  45.             }  
  46.             json.append("}");  
  47.         }catch (Exception e) {  
  48.             e.printStackTrace();  
  49.         }  
  50.         return JSONObject.fromObject(json.toString());  
  51.     }  
  52.       
  53.       
  54. }  

      在processObjectValue这个方法里重写,具体请看代码,另外在构造方法里我给出了两个参数,一个是需要留下来的属性名,通过数组传递,另一个是一个Class<?> type,也是相关上面说到例子中的Organzition.class,是用来在后面通过该class调用java反射机制获取属性值,在取到相关属值后组装成字符串,最后通过JSONObject.fromObject来输出,不这样输出会有问题,至于什么问题,有好奇心的同学自己试试

下面是调用方法:

Java代码   收藏代码
  1. jsonConfig.registerJsonValueProcessor(Organzition.class,   
  2.        new ObjectJsonValueProcessor(new String[]{"orgName","orgId"},Organzition.class));  
 

其中,Organzition.class是你要处理的属性类型


第二篇文章:

 有一个A表,和B表,是one to many的关系。当我将B表从数据库中查出后.

 通过:

  1. JSONArray responseJsonMsgs=JSONArray.fromObject(list);

转成Json对象时报错:    There is a cycle in the hierarchy!

 

稍微想想就能明白,这里产生了死循环查询(跟hibernate的配置文件有关)。

 

解决方案,在转成Json对象的时候过滤掉bean中引起死循环查询的属性(一般为设置的外键)。

 

  我这里写了一个通用的过滤器对象,大家可以借鉴下

 

  1. package com.cfc.web.msgcenter;
  2. import net.sf.json.JsonConfig;
  3. import net.sf.json.util.PropertyFilter;
  4. public class JsonFilter {
  5.     public static JsonConfig getFilter(final String[] s){
  6.         JsonConfig config = new JsonConfig();
  7.         config.setJsonPropertyFilter(new PropertyFilter(){
  8.             
  9.             public boolean apply(Object source, String name, Object value) {
  10.              if(juge(s,name)) {
  11.               return true;
  12.              } else {
  13.               return false;
  14.              }
  15.             }
  16.             
  17.             public boolean juge(String[] s,String s2){
  18.                 boolean b = false;
  19.                 for(String sl : s){
  20.                     if(s2.equals(sl)){
  21.                         b=true;
  22.                     }
  23.                 }
  24.                 return b;
  25.             }
  26.            });
  27.         return config;
  28.     }
  29. }

 

转换的时候调用过滤器

  1. JsonConfig config = JsonFilter.getFilter(new String[]{"gameclass"});//String数组中存储的是要过滤的属性
  2. JSONArray responseJsonMsgs=JSONArray.fromObject(list,config);

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/tang7837010/article/details/36414571
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-21 22:19:55
  • 阅读 ( 1193 )
  • 分类:前端

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢