将具有关联关系的两个表从hibernate查询出来转成json对象时报错

第一篇文章:

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

一种是通过

Java代码  

  1. jsonConfig.setExcludes(new String[]{"dianYuanHeSuans"})

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

Java代码  

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

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

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

假如说我们一个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. private String[] properties;
  11. /**
  12. * 需要做处理的复杂属性类型
  13. */
  14. private Class<?> clazz;
  15. /**
  16. * 构造方法,参数必须
  17. * @param properties
  18. * @param clazz
  19. */
  20. public ObjectJsonValueProcessor(String[] properties,Class<?> clazz){
  21. this.properties = properties;
  22. this.clazz =clazz;
  23. }
  24. @Override
  25. public Object processArrayValue(Object value, JsonConfig jsonConfig) {
  26. return "";
  27. }
  28. @Override
  29. public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
  30. PropertyDescriptor pd = null;
  31. Method method = null;
  32. StringBuffer json = new StringBuffer("{");
  33. try{
  34. for(int i=0;i<properties.length;i++){
  35. pd = new PropertyDescriptor(properties[i], clazz);
  36. method = pd.getReadMethod();
  37. String v = String.valueOf(method.invoke(value));
  38. json.append("‘"+properties[i]+"‘:‘"+v+"‘");
  39. json.append(i != properties.length-1?",":"");
  40. }
  41. json.append("}");
  42. }catch (Exception e) {
  43. e.printStackTrace();
  44. }
  45. return JSONObject.fromObject(json.toString());
  46. }
  47. }

在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. public boolean apply(Object source, String name, Object value) {
  9. if(juge(s,name)) {
  10. return true;
  11. } else {
  12. return false;
  13. }
  14. }
  15. public boolean juge(String[] s,String s2){
  16. boolean b = false;
  17. for(String sl : s){
  18. if(s2.equals(sl)){
  19. b=true;
  20. }
  21. }
  22. return b;
  23. }
  24. });
  25. return config;
  26. }
  27. }

转换的时候调用过滤器

  1. JsonConfig config = JsonFilter.getFilter(new String[]{"gameclass"});//String数组中存储的是要过滤的属性
  2. JSONArray responseJsonMsgs=JSONArray.fromObject(list,config);
时间: 2024-10-21 00:42:43

将具有关联关系的两个表从hibernate查询出来转成json对象时报错的相关文章

sql两个表的组合查询以及yii下使用数据库查询

sql两个表的组合查询  使用 join on 例如:两个表查询: select u.username, t.title from user u join task t on u.id = t.id; 其中  user u 是用来把表名简化   join则是加入其他的表    on则是表示查询的条件   u.username 则是表示user表中的username字段 同样的道理  多表查询的原理也是一样的 这是sql语句: select * from user u join task t on

在db2中 两个数据库之间的两个表的联合查询

大家好,今天遇到了在db2中 两个数据库之间的两个表的联合查询我知道oracle中有dblink,可是不知到db2的两个数据库联合查询怎么处理我找了类似于比如两个数据库: db1,db2用户名密码select * from db1.用户名.密码,db2.用户名.密码 where db1.NM=db2.NM可是这样不好用啊请各位帮忙谢谢 DB2有联邦数据库的,你可以查一下. 1.要看目录数据库请用:db2 list db directory这些信息应该是放系统表中.(既不是什么注册表.也不是什么文

关于mysql当中给数据量特别大的两个表做关联查询的时候解决查询速度很慢的解决方法

今天碰到了两个表做关联查询的mysql,这两个表的数据量都是特别大的,有一个表的数据是上亿条的数据,有一个是几百万的数据, 查询的速度是特别慢,然后我看了一下执行计划,下面是执行执行计划: 看到上面这个图这个数据量是特别大的,这个查询起来的肯定是非常慢的,而且他的类型都是ALL类型,也就是都是全表进行扫描的.然后在网上找资料,然后发现我们可以给关联的字段建索引. 于是我给关联字段建立了索引,然后就发生了下面的变化: 整个的行数就成不知道多少个数量级的情况在下降,整个的查询速度也是加快了额很多,现

sas中的sql(3) 标签,格式化输出,子查询,大于两张表的联合查询(暂缺)

1.1:Specifying Column Formats and Labels (SAS enhancements. ) proc sql outobs=15; title 'Current Bonus Information'; title2 'Employees with Salaries > $75,000'; /*title可以放在sql之前或sql与select之间*/ select empid label='Employee ID', /*label=放在变量之后*/ jobcod

两张表数据模糊查询

判断pg_cust_analysis_all表中的’客户名称‘字段是否包含 ICP.dbo.a 表中的ai字段中的数据 eccrc_rep.dbo.pg_cust_analysis_all.客户名称是公司名 ICP.dbo.a.ai是‘ai’发音的汉字 这个需求是计算公司名中包含“爱”同音字 select count(*) from ICP.dbo.a a,eccrc_rep.dbo.pg_cust_analysis_all b where charindex(a.ai,b.客户名称)<>0

Ajax表单序列化后的数据格式转成Json发送给后台

<script> $(function(){ //表单转json函数 $.fn.serializeObject = function(){ var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name] !== undefined) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(th

使用jquery将表单自动封装成json对象 /json对象元素的添加删除和转换

$.fn.serializeObject = function () { var o = {}; var a = this.serializeArray(); $.each(a, function () { if (o[this.name]) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.v

T-SQL数据库中两个表之间的操作

--根据另一张表修改表中的数据 update Admin_FCOutDt set oLastId=T.contractID from (select crm_contract.contractTopic,crm_contract.contractID from Admin_FCOutDt left join crm_contract on Admin_FCOutDt.ContractName=crm_contract.contractTopic )T where Admin_FCOutDt.Co

分享一个小工具:Excel表快速转换成JSON字符串

在游戏项目中一般都需要由策划制作大量的游戏内容,其中很大一部分是使用Excel表来制作的.于是程序就需要把Excel文件转换成程序方便读取的格式. 之前项目使用的Excel表导入工具都是通过Office Excel组件来实现数据访问的,效率十分令人不满.一个端游项目一般要上百个表格,手游项目20.30个表格基本也是要的,于是表格导入程序的过程一般要几分钟,项目后期要接近半个小时. 此次分享的小工具,在速度上有质的飞越,比上述方法实现的工具有接近100倍的速度提升: 完整项目源代码下载:https