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     }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM