经管资源库项目的总结笔记

在学完hibernate和struts2之后,便在别人在带领下参与了本校的一个资源库项目,主要是对资源的一些管理和上传下载等操作。

毫无疑问,在实践中总能发现很多学习时无法发现的新的问题,对hibernate和struts2的一些理解也逐步深化。。

1.hibernate配置:

 

  1)多对一查询时,必须在属性里面显式配置fetch=”join”,才能查出引向的类否则默认不会进行多表查询。

  2)多对多查询时的fetch属性最好为subselect,这样既不会像join一样输出重复数据,而且也能减少hibernate产生的select语句。

  3)在一对多时 inverse=false的一方删除时,会把多的一方的外键id设置为null再删除,所以外键id最好设置成可空类型。

    而多对多时,inverse=false的一方删除时,会自动的删除第三张表关系表中的数据。

  4)QBC中的关联查询。通过Criteria 进行多表关联条件查询。

   /*这种写法是正确的*/
    Criteria criteria = getSession().createCriteria(entityClass);
    criteria.add(Restrictions.eq("repUser.id", 1));

    /*
   这种写法却是错误的
   因此lz猜测可能是懒加载导致这种写法失败的。因此百度了些博客,找到了正确的解决方案
     */
   Criteria criteria = getSession().createCriteria(entityClass);
   criteria.add(Restrictions.eq("repUser.username", "user"));

  

解决办法1:通过对类属性创造别名的方式来创造类属性的条件查询

 DetachedCriteria criteria = DetachedCriteria.forClass(MainClass.class); 
   criteria
   .add(Restrictions.eq("type", new Integer(1)))
   .createAlias("subs", "s")
   .add(Restrictions.eq("s.value", new Integer(2)));

  

  

解决办法2:直接用Restrictions.sqlRestriction()方法来查询。

criteria.add(Restrictions.or(
            Restrictions.sqlRestriction("(select u.username from rep_user u where u.id={alias}.userid) like '%user%' "), 
            Restrictions.sqlRestriction("(select a.username from rep_admin a where a.id={alias}.adminid) like '%admin%'")));

  

需要注意的是如果要用到查询的类的属性,是用{alias}进行引用,然后就可以通过子查询的方式查出查询的类的类属性。考虑到项目代码较多,因此采用的是第二种方法

2.hibernate 的对象中有哪些是代理对象

  最近在项目中遇到了十分坑爹的failed iniliazed lazy...session is closed 的错误,后来调试和百度了很久才知道这是因为调用了代理对象的方法引起的。具体而言就是在dao层中的一个方法调用了pojo的一个set属性的size()方法,而这个pojo又恰好是用hibernate取出来的,里面的set属性是个代理对象,并不是定义的hashset,结果就悲剧了。。

在调试和百度了许久之后,才发现如果配置文件里面对set属性配置了lazy或者啥也没配(默认就是lazy),那么你无论是通过

  1.get(),

  2.还是criteria,

  3.甚至是query("select u from User")

这样取出整个对象 的操作,取出的对象虽然不是代理对象(一般的教程都会提及get与load的区别,但是没说它的属性不是代理对象。。),但是这个属性确实代理对象,所以在调用这个方法的时候会出现这种错误。然而由于底层代码的jar包冲突等原因spring的很多功能无法使用,并且时间紧迫也来不及找bug,于是我是采用getCurrentSession的方式的。。最终的解决办法是尽量避免这样调用,如果实在需要这个属性(多对多的),那么就只能重新查询一次获取这个set自己用setXxx()的方法给它赋值。。

正在更新中。。。