com.sun.jdi.InvocationException不一定就是Hibernate的错
在HibernateDaoSupport的子类中有如下语句:ListretValue=getHibernateTemplate().find("from ViewAttachAuth where1=1"),其中ViewAttachAuth是自定义的实体对象,映射到数据库中的一个视图,按理说retValue应该是一个类型为ArrayList的对象,并且retValue中的每一个元素都是ViewAttachAuth对象,可是我在调试的时候发现返回对象的toString()方法得到的竟然是"com.sun.jdi.InvocationException occurred invokingmethod.",和普通的ArrayList对象的toString方法显然是不一样的,但是如果把它当做List接口来使用的话并不会出现问题,而如果System.out.println(retValue)的话则会出现java.lang.StackOverflowError堆栈溢出的错误,造成程序崩溃。综合网上的相关帖子以及自己使用Hibernate的经验初步断定这个现象和Hibernate的缓存以及延迟加载策略相关,不过ViewAttachAuth对应的视图中的记录并不多,只有四五条,在这么小的数据量的情况下Hibernate不至于启动二级缓存什么的吧,看来还得好好想想是怎么回事。
接下来的几分钟里我的脑海中一直出现一个字符串:toString,会不是toString这个方法本身的问题呢。按照这个思路我检查了我自己的实体类ViewAttachAuth,发现它的toString方法是下面这样定义的。
public String toString() { return org.apache.commons.lang.ObjectUtils.toString(this); }
于是我尝试着改成下面这样:
public String toString() { StringBuffer sb=new StringBuffer("["); sb.append("lsh="+getLsh()+","); sb.append("aname="+getAname()+","); sb.append("asize="+getAsize()+","); sb.append("description="+getDescription()+","); return sb.toString(); }
很不幸(^_^),问题解决了。于是我忍不住想看看org.apache.commons.lang.ObjectUtils.toString(Objectobj)的源码,看看里面究竟有什么魔力让我的程序崩溃,接下来的一幕让我惊呆了,下面是ObjectUtils中toString方法的源码片段:
public static String toString(Object obj) { return obj == null ? "" : obj.toString(); }
看到这里我最初的toString方法能引起程序崩溃也就不足为奇了:又是死循环!程序员的宿敌!