首先說明一下,hibernate的延遲加載特性(lazy)。所謂的延遲加載就是當真正須要查詢數據時才執行數據加載操做。由於hibernate當中支持實體對象,外鍵會與實體對象關聯起來。若是沒有這一特性,當查詢某一個含有外鍵的實體對象時,hibernate會把其餘實體對象的數據都查詢出來。簡單的來講,當你想查詢某個對象時,實際上調用了多條查詢語句。有了延遲加載特性,就避免了這種狀況的發生,當你真正的使用get另一個實體對象時,纔再執行下面一條查詢語句。
但有些時候,這個特性卻會給咱們應用中帶來一些問題。
這個問題相信你們並不陌生了,hibernate的延遲加載(lazy)特性的確不錯的優勢,若是沒了這個特性,我相信你們在處理一些外鍵的對象時會頭大起來,由於效率十分的低。甚至不少人都以爲使用jdbc要比hibernate要高效甚至方便得多,而迫使不去使用hibernate。
我想說,沒錯,使用jdbc在效率上的確可能要快許多,但差距也不會太大的,由於hibernate自己就支持多種查詢方式,SQL、HQL、 DetachedCriteria等。而相反的,hibernate在維護性上比jdbc強不少,由於是實體對象的關係。我相信若是您使用過jdbc來實現註冊功能的話,會深有體會。
提示session已關閉(no session or session was closed) 觸發這個問題的緣由在於,hibernate在查詢操做完畢的時候會自動的把session關閉掉,爲了下降使用的資源。但問題也這樣產生了,不要忘了以前所說的hibernate特性,此時再調用get實體方法的時候就會有可能出現這個錯誤。由於session已經關閉而不能繼續執行查詢了。
解決思路:
一、關閉延遲加載特性。
操做起來比較簡單,由於hibernate的延遲加載特性是在hbm配置裏面可控制的。默認lazy="true",在many-to-one中添加屬性lazy="false",就不詳細敘述了。
<many-to-one name="category" lazy="false" class="com.penglei.onlineshop.category.vo.Category" column="cid"></many-to-one>
|
但使用這個解決辦法帶來的隱患是十分大的。
首先,出現no session or session was closed就證實了您已經在使用外鍵關聯表,若是去掉延遲加載的話,則表示每次查詢的開銷都會變得十分的大,若是關聯表越多,後果也能夠想象獲得。因此不建議使用這個方法解決。
二、在session關閉以前把咱們想要查詢的數據先獲取了。
然而有時會出現一種狀況就是使用第一種方法並不能解決問題。這時咱們須要瞭解一下session何時關閉,也就是它的生命週期。一般狀況下hibernate會在查詢數據關閉session,而使用getHibernateTemplate().get方法查詢後會延遲關閉的時間。會在事務結束後才關閉。
使用攔截器(Interceptor)或過濾器(Filter)控制session。
spring爲解決hibernate這一特性提供的解決方案,能夠有效的控制session生命週期。
在web.xml添加一個攔截器:
<!-- 用於解決懶加載的問題 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
|
重要:網上有不少文檔說加入這段代碼便可解決懶加載的問題,可是對於不少新手來講,有不少疑問,爲何把這段代碼粘貼進去了好像仍是沒有什麼用。
因此須要注意的是這段代碼必定要放在web.xml文件的最開始,如此方可解決問題。