【環(huán)境參數(shù)】
環(huán)境:SSH框架
【問題描述】
NoSession問題
HibernateTemplate對象提供的方法如果使用“延遲加載”,Session對象的管理不受開發(fā)者控制,此時如果在表現(xiàn)層獲取延遲加載的數(shù)據(jù),
則會拋出“LazyInitializationException”異常,如下圖所示。
【原因分析】
原因總結:Session的存活期太短,在Session已經關閉的情況下,App讀取持久化對象中的非OID的屬性從而報錯。
假設load()方法獲得的對象是User對象。
“延遲加載”的特點:
在Hibernate沒有關閉Session時,App可以隨時去讀取“延遲數(shù)據(jù)(通過讓Hibernate重新加載去獲得數(shù)據(jù))”。
load()方法獲得的User對象是一個“只有ID屬性”的對象,只要App不去使用User對象中的“非ID屬性”,則User對象中永遠都只有ID屬性,這樣可以提高性能。
當App去調用對象X中的非ID屬性時,比如name和age屬性,正常情況下,Hibernate會去加載name和age屬性,然后JVM再調用toString()方法,并且成功地完成打印。
但若在Hibernate去加載name和age屬性時,Session已經關閉了,則Hibernate就無法去加載得到非ID屬性了,此時就會拋出異?!癓azyInitializationException”。
Session為什么會關閉呢?
當我們提交事務時,就會自動把Session給關閉了。
【解決方案】
該解決方案由Spring提供:OpenSessionInView。
(1)主要思路
將Session的存活期延長,綁定Session。
(2)產生該方案的思路
客戶端發(fā)一個請求,則位于服務器端的Spring創(chuàng)造一個Session,當請求結束了,才會把Session關閉,這樣,就將Session與請求綁定在一起了。
從發(fā)送請求到請求結束,這整個流程都位于一個線程,在此,將Session對象綁定到該線程上,在Hibernate知識體系中,就有一個關于“當前線程綁定Session”的專題,講的也就是這個概念。
客戶端每次發(fā)送請求時,都要去將Session綁定到線程上,這樣比較麻煩,能否有簡化途經呢?比如Spring的AOP。
1)可選方案一:利用Spring的AOP。
方案一可行性:不靠譜。
為什么方案一不行?
因為在客戶端發(fā)送的請求在到達服務器的過程中,Spring還沒有開始工作。Spring若想綁定東西,要綁定的東西必須是“代碼”,
“請求對象和響應對象的創(chuàng)建”是由服務器端的HTTPD守護程序完成的。而Spring是位于Web容器中的,而且Spring容器隨著某個WebApp的啟動而創(chuàng)建的。此時Spring還沒有開始工作,而請求對象已經被HTTPD守護程序創(chuàng)建了,此時,Spring是不可能將Request對象同Session對象進行綁定的,因此,AOP是不能完成該功能的。
2)可選方案二:利用監(jiān)聽器
方案二可行性:不靠譜。
<listener>監(jiān)聽器:監(jiān)聽器是啟動服務器時一次性運行的。
3)可選方案三:利用過濾器
<filter>過濾器:過濾器是每當用戶的請求Request對象到達WebApp時以及Response對象出WebApp時使用的。
(3)終極解決方案
1)簡述:OpenSessionInView翻譯過來就是:在表現(xiàn)層打開Session。
2)作用:
將Session對象的創(chuàng)建交給當前線程管理,當前線程維護著一個“Session的連接池”。每當用戶發(fā)送一個請求,filter在接收到用戶的請求Request后,就會將Session對象綁
定到該請求上。
當請求被處理完畢,返回響應Response時,Response會再次經過filter的處理,Response之前被綁定的Session會被filter回收,然后放入到“Session的連接池”中。
當下次用戶再次發(fā)送請求時,仍然重復上述過程。
3)代碼:
在web.xml中設置過濾器OpenSessionInViewFilter。
1 2 3 4 5 6 7 8 9 | <!-- 配置OpenSessionInView --> <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> |
讀者如要轉載,請標明出處和作者名,謝謝。
地址01:http://space.itpub.net/25851087
地址02:http://www.cnblogs.com/zjrodger
作者名:zjrodger
聯(lián)系客服