关于json-lib 和hibernate一起使用的时候出现死循环的解决办法

在我们使用json-lib和hibernate开发的时候,一开始的时候会遇到转换json数组的是出现死循环问题,下面就把我的经历记录一下,可能帮助到大家。

我的实体是这样的,用户和群两个实体(他们之间的关系是多对多,一个用户可在多个群中,一个群中有多个用户),对象模型如下:(即:实现的时候是双向的,用户可以取到群的信息,群里可以去到用户信息)

Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public  class  User{
   private  int  id;
   private  String name;
   private  Set<Group> groups =  new  HashSet<Group>();
 
   //getter or setter .... 
}
 
public  class  Group{
   private  int  id;
   private  String name;
   private  Set<User> users =  new  HashSet<User>();
 
   // getter or setter .... 
}


关系模型:
三张表:l_user(id,name)
        l_group(id,name)
        l_user_group(user_id,group_id);

配置的时候都设置为fetch 为懒加载的方式,现我有如下需求:
1.取出用户的时候,取出用户所在的群的所有信息,即,取一个用户,我还能够得到用户的所在所有群的名字

针对这个需求我是这样的写的dao的:
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
     public  User findByExample(User user) {
         // TODO Auto-generated method stub
         User rs =  null ;
         Session session = getSession();
         try {
         session.beginTransaction().begin();
         
         Query hql = session.createQuery( "from User u where u.id=:id and u.password=:psd" );
         hql.setParameter( "id" ,user.getId());
         hql.setParameter( "psd" , user.getPassword());
         rs = (User)hql.uniqueResult();
         //加载群信息,因为使用的lazy的,所以需要加载
         Iterator<Group> iterator = rs.getGroups().iterator();
         while (iterator.hasNext()){
             Group g = iterator.next();
             Hibernate.initialize(g);
         }           
         session.beginTransaction().commit();
         
         } catch (Exception e){
             e.printStackTrace();
             session.getTransaction().rollback();
         } finally {
             if (session != null &&session.isOpen())
             {
                 session.close();
             }
         }           
         return  rs;
     }


在action中的调用如下:
Java code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public  String list(){
         User u = userDAO.findByExample( new  User( 1 , null , "123456" , null ));
 
         if (u!= null ){
//下面代码为测试
System.out.println(u.getName());
Iterator<Group> it = u.getGroups().iterator();
while (it.hasNext()){
     System.out.println(it.next().getName());
     
}
//打印结束
 
JsonConfig jsonConfig =  new  JsonConfig();
jsonConfig.setJsonPropertyFilter( new  PropertyFilter() {
     @Override
     public  boolean  apply(Object arg0, String arg1, Object arg2) {
         // TODO Auto-generated method stub
                 //问题在此处,如何过滤group中的users集合,只是去到名字,不取里面的成员信息
         return  (arg0  instanceof  Group &&arg1.equals( "users" ) && arg2== null );
     }
});
             //jsonrs字符串包含的是用户的信息
             rsobj = JSONObject.fromObject(u,jsonConfig);
         } else { //不存在这样的用户,用户的为null,json结果为null
             rsobj =  null ;
         }
         return  "list" ;
     }


运行结果:
aaaaa
group1
2013-12-10 19:12:50 freemarker.log.JDK14LoggerFactory$JDK14Logger error
严重: Template processing error: "Method public java.lang.String org.apache.commons.lang.exception.NestableRuntimeException.getMessage(int) threw an exception when invoked on net.sf.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.model.Group.users, no session or session was closed"

Method public java.lang.String org.apache.commons.lang.exception.NestableRuntimeException.getMessage(int) threw an exception when invoked on net.sf.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.model.Group.users, no session or session was closed
The problematic instruction:
----------
==> ${msg[0]} [on line 68, column 29 in org/apache/struts2/dispatcher/error.ftl]
----------


,这里是我自己傻逼了,上面我的解题思路是对的,就是中间的一句代码写错了

Java code
?
1
2
3
4
5
6
7
8
jsonConfig.setJsonPropertyFilter( new  PropertyFilter() {
     @Override
     public  boolean  apply(Object arg0, String arg1, Object arg2) {
         // TODO Auto-generated method stub
                 //问题在此处,如何过滤group中的users集合,只是去到名字,不取里面的成员信息
         return (arg0 instanceof Group &&arg1.equals("users") && arg2==null );
     }
});

红色的部分用法出错了,不该使用&&,要使用||,改为
Java code
?
1
2
3
4
5
6
7
8
jsonConfig.setJsonPropertyFilter( new  PropertyFilter() {
     @Override
     public  boolean  apply(Object arg0, String arg1, Object arg2) {
         // TODO Auto-generated method stub
                 //问题在此处,如何过滤group中的users集合,只是去到名字,不取里面的成员信息
         return ((arg0 instanceof Group &&arg1.equals("users")) || arg2==null);
     }
});

问题就解决了,哎,自己真是S B啦。。。。


也就是说,如果我们在开发的时候有类似我们上面的需求的时候,可以把加载方式设置为lazy ,之后再DAO里按需,再在转换json的时候使用过滤器,当然设为lzay,转换json的时候使用过滤也行,但是既然不要他,为何去加载他呢,不是浪费么,是吧。所以这里可以自己灵活的使用,根据自己的需求选择加载方式,而处理死循环或者session关闭(lzay是才会出现的问题)问题时,使用JsonConfig的PorpertyFilter过滤一下就行。


关于PorpertyFliter 里面的三个参数,其实网上可以看到,这里也顺便说一下,arg0-->要过滤的属性的所有者(如:我的例子里面的users这个集合属性属于Group),arg1为需要过滤的属性名,arg2为属性的值();最终返回值为true表示过滤,否则不过滤


------------------------------------------分割线----------------------------------------------------------------

这是当初在使用struts2的时候没有了解struts2的json返回的特点,struts2和springMVC的返回json的效果其实可以一样的,直接返回查询的结果集 如:List<User>等,但是只要使用了hibernate的地方,出现了双对引用的时候就必然会出现这种问题。解决方式还是要使用json过滤。

https://github.com/FunHuan/hehe  此链接是本人总结的解决springMVC整合hibernate的时候出现的该错误的解决办法。


另外,MyBatis这个数据层框架还是不错,可以考虑用这个代替hibernate。有兴趣的同学可以研究下。



希望能够帮助到大家,谢谢



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值