使用OpenSessionInViewFilter方案解決Hibernate懶加載異常的問題
在項目練習的時候,遇到了這個懶加載異常,當時解決的方法是在配置文件中設置lazy="false"。該方法有很到缺點,效率極低,我們將所有相關聯的數據都查詢了,頻繁的查詢降低了效率!!不建議采用
Web程序中的懶加載異常說明及解決方案
異常說明
當一個請求來了之后,先執行Action,在執行結果。在action里面有Service業務層,調用Service,Service做業務處理。
開始執行Service方法的時候,開始開啟事務和Session,Service方法結束或回滾提交事務,會自動關閉Session。
在Service里面查詢列表加載對象的時候,但是其相關連的對象并沒有加載,但是Session關閉了,關聯對象最終沒有加載,在頁面中用到了懶加載屬性,但是是在之前加載的,且Session已經關閉了,所以有了懶加載異常,說沒有Session。
解決方案
從上面的異常說明中可以得知,主要原因是在頁面中沒有Session,那么我們可以使Session不關閉,不關閉Session又會出現問題,那么我們就在整個請求的過程中添加一個過濾器或者攔截器,過濾器或攔截器是先進后出。我們在過濾器或攔截器中關閉Session,也就是在當頁面顯示一些數據后,再在過濾器或攔截器里面關閉Session就可以了。但是需要設置當事務提交之后,不需要關閉Session。在spring中已經有一個過濾器可以幫助我們在過濾器中關閉Session了。OpenSessionInViewFilter
配置方案
第一步:web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>OA</display-name>
<!-- 配置spring的監聽器,用于初始化spring對象 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置Spring的用于解決懶加載問題的過濾器,一定要配置在Struts2之前 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- 配置Struts2的主過濾器 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
注意:攔截的是所有的action,而且在Action里面調用的是Service,與struts的配置Action的擴展名一樣
第二步:struts配置
<!-- 配置擴展名為action -->
<constant name="struts.action.extension" value="action" />
不過,當整個系統中出現兩個請求的,并且不是一個請求的時候,還是會出現懶加載異常。比如,一個是SSH框架里面的Struts2里面的請求,里面已經已經通過OpenSessionInViewFilter解決的懶加載異常,但是當系統需要的Servlet的監聽器里面需要初始化某些數據的時候,而且這些數據與其他數據有關系的時候,還是會出現懶加載異常,所以還要在實體配置文件中配置lazy="false"屬性。