zoukankan      html  css  js  c++  java
  • no Session问题,即延迟加载

    no Session问题,即延迟加载

      在开发中,相信很多同学都遇到过这个问题,也就是说当我们在前台页面用表达式语言取值的时候,会发现程序后台报错了,显示的错误时no session,其实这个就是延迟加载的问题,下面进行简单的谈一谈,并提出几点解决的建议。

      延迟加载的问题是指当我们调用完action中的某个方法,在jsp页面要显示我们想要的信息的时候,发现在dao中打开的session已经关闭了。

      如下图,第一个箭头表示的是我们通过前台页面返回action,action会通过service层调用dao去访问数据库,当从数据库中把值取出来之后返回到action中,再返回到前台页面中去。我们知道,只有我们在调用某个类getter()方法的时候才会打开session,可惜的是,在hibernateTemplate中注入的sessionFactory在action返回到前台页面前已经关闭了,也就是这个时候再前台页面调用getter()方法,想要打开session,但是sessionFactory已经关闭了,所以后台就会报错,显示no session。意思就是找不到session。

           

    这个时候可以采用以下几种方式解决:

      1、  将pojo类中的fetch的lazy改成eager,这个时候如果你的操作页面中牵扯了多个外键关系的话,就要把这几个外键关系的fetch的lazy都改成eager。这里的lazy是代表懒加载的意思,也就是说在查询一个表的信息的时候,不会把关联的表的信息查找出来。而如果改成eager的话,就代表说把关联的表的信息也全部加载出来。很明显,这样的操作会加载一些我们压根就不需要的操作,也可能我们只需要加载某张表的信息的时候,却自动的把关联的表加载出来。所以这种操作性能是很差的,不建议使用。

      2、  配置过滤器openSessionInViewFilter,顾名思义,这个过滤器是指把在页面中打开session的服务,也就是说延迟session打开的状态,在前台页面中调用完方法之后再关闭session,配置如下: 

    <filter>

    <filter-name>OpenSessionInView</filter-name>

    <filter-class>

    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

    </filter-class>

    </filter>

    <filter-mapping>

             <filter-name>OpenSessionInView</filter-name>

             <url-pattern>/*</url-pattern>

    </filter-mapping> 

        要注意的是这个过滤器要配置到struts的过滤器的前面,不然就不起作用了,因为配置在struts过滤器的后面的话,数据已经接收完毕了,也就是说sessionFactory已经关闭了,这个时候你再来配置说把session延长到view中,已经没作用了,所以要把openSessionInViewFilter配置在struts前面。但是要注意的是,上面的配置并不是完整的配置,完整的配置应该是在filter里面配置如下信息: 

    <filter>

             <filter-name>OpenSessionInView</filter-name>

             <filter-class>

                       org.springframework.orm.hibernate3.support.OpenSessionInViewFilter

             </filter-class>

             <init-param>

                       <param-name>singleSession</param-name>

                       <param-value>true</param-value>

             </init-param>

    </filter>

    <filter-mapping>

             <filter-name>OpenSessionInView</filter-name>

             <url-pattern>/*</url-pattern>

    </filter-mapping> 

        上面配置的意思是表示配置成单例的session。但是如果按以上配置的话,在后续session的操作中是会出现问题的,而如果不配置成单例的话,性能是很低的。所以这个方法也不建议。

      3、  手工操作(建议)  

        a)   在action中操作

        在action中操作指的是我们在传递对象到前台页面(这里主要是jsp)的时候,多传递一些对象到前台去。比如在action中我们需要传递question对象到前台中进行展示,但是同时也需要查找出这个问题所属的类型type,这个时候就可以在页action中除了传递question对象之外,再根据这个question的其他属性(如tid)来查找到对应的type,再把type对象传递到页面中。不过这样做比较麻烦的是除了自己要在dao中加方法外,如果一个页面管理着好几个数据表的话,传递的对象属性相对就比较多了。

        b)   在daoimpl中操作(强烈建议)

      在daoimpl中进行手工设置是本人觉得最合适的方式,也是比较推崇的一种。用这种方法的话,在daoimpl的操作中,就要用到hibernateCallback的内部类方法了。也就是说调用super.getHibernateTemplate().execute()方法,编写内部类,在得到一个list集合之后,取出集合的对象,调用要用到的关联类的getter()方法,就可以打开session了,一般不用调用主键的getter()方法。

    范例(只是部分代码,无法运行,仅供参考):

     1 public Question findById(final Integer id) throws Exception {
     2         return super.getHibernateTemplate().execute(
     3                 new HibernateCallback<Question>() {
     4                     @SuppressWarnings("unchecked")
     5                     public Question doInHibernate(Session session)
     6                             throws HibernateException, SQLException { // 用hibernateCallBack
     7                         String hql = "From Question AS q WHERE q.qid=?"; // 构建hql语句
     8                         Query query = session.createQuery(hql); // 创建query
     9                         query.setInteger(0, id); // 设置占位符
    10                         List<Question> all = query.list(); // 得到具体的list集合,里面只存放一个question对象
    11                         if (all.size() > 0) { // 集合不为空
    12                             Question vo = all.get(0); // 取出question对象
    13                             vo.getType().getTitle(); // 调用type的getTitle方法,这样会把type相关的session打开,在jsp调用时数据还可以调用
    14                             vo.getAnswers().size(); // 调用getAnswers()方法,把session打开,消除延迟加载
    15                             if (vo.getAnswer() != null) { // 如果存在最佳答案
    16                                 vo.getAnswer().getContent(); // 消除延迟加载
    17                             }
    18                             return vo; // 返回vo
    19                         }
    20                         return null;
    21                     }
    22                 });
    23     }
  • 相关阅读:
    Understanding performance, load and stress testing
    添加查看原型的插件
    Navicat Premium 15安装破解
    APP 测试 与 WEB 测试的本质区别
    app专项测试(稳定性测试、安全性测试)
    ubantu在登录界面一致循环的问题
    Ubuntu虚拟机安装
    装WIN7
    Linux线程模型浅析
    django中常用的数据查询方法
  • 原文地址:https://www.cnblogs.com/littleQin/p/3652430.html
Copyright © 2011-2022 走看看