文章出處
文章列表
首先說明一下,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已經關閉而不能繼續執行查詢了。
解決思路:
1、關閉延遲加載特性。
操作起來比較簡單,因為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就證明了您已經在使用外鍵關聯表,如果去掉延遲加載的話,則表示每次查詢的開銷都會變得十分的大,如果關聯表越多,后果也可以想象得到。所以不建議使用這個方法解決。
2、在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文件的最開始,如此方可解決問題。
結語
> 如果你還需要了解更多技術文章信息,請繼續關注白衣秀才的博客
個人網站:http://penglei.top/
Github:https://github.com/whitescholars
微博:http://weibo.com/u/3034107691?refer_flag=1001030102_&is_all=1
文章列表
全站熱搜