使用OpenSessionInViewFilter方案解決Hibernate懶加載異常的問題
在項(xiàng)目練習(xí)的時(shí)候,遇到了這個(gè)懶加載異常,當(dāng)時(shí)解決的方法是在配置文件中設(shè)置lazy="false"。該方法有很到缺點(diǎn),效率極低,我們將所有相關(guān)聯(lián)的數(shù)據(jù)都查詢了惦积,頻繁的查詢降低了效率!猛频!不建議采用
Web程序中的懶加載異常說明及解決方案
異常說明
當(dāng)一個(gè)請(qǐng)求來了之后狮崩,先執(zhí)行Action,在執(zhí)行結(jié)果鹿寻。在action里面有Service業(yè)務(wù)層睦柴,調(diào)用Service,Service做業(yè)務(wù)處理毡熏。
開始執(zhí)行Service方法的時(shí)候坦敌,開始開啟事務(wù)和Session,Service方法結(jié)束或回滾提交事務(wù)痢法,會(huì)自動(dòng)關(guān)閉Session狱窘。
在Service里面查詢列表加載對(duì)象的時(shí)候,但是其相關(guān)連的對(duì)象并沒有加載财搁,但是Session關(guān)閉了蘸炸,關(guān)聯(lián)對(duì)象最終沒有加載,在頁面中用到了懶加載屬性尖奔,但是是在之前加載的搭儒,且Session已經(jīng)關(guān)閉了,所以有了懶加載異常越锈,說沒有Session仗嗦。
解決方案
從上面的異常說明中可以得知膘滨,主要原因是在頁面中沒有Session甘凭,那么我們可以使Session不關(guān)閉,不關(guān)閉Session又會(huì)出現(xiàn)問題火邓,那么我們就在整個(gè)請(qǐng)求的過程中添加一個(gè)過濾器或者攔截器丹弱,過濾器或攔截器是先進(jìn)后出。我們?cè)谶^濾器或攔截器中關(guān)閉Session铲咨,也就是在當(dāng)頁面顯示一些數(shù)據(jù)后躲胳,再在過濾器或攔截器里面關(guān)閉Session就可以了。但是需要設(shè)置當(dāng)事務(wù)提交之后纤勒,不需要關(guān)閉Session坯苹。在spring中已經(jīng)有一個(gè)過濾器可以幫助我們?cè)谶^濾器中關(guān)閉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的監(jiān)聽器摇天,用于初始化spring對(duì)象 -->
<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里面調(diào)用的是Service,與struts的配置Action的擴(kuò)展名一樣
第二步:struts配置
<!-- 配置擴(kuò)展名為action -->
<constant name="struts.action.extension" value="action" />
不過为鳄,當(dāng)整個(gè)系統(tǒng)中出現(xiàn)兩個(gè)請(qǐng)求的裳仆,并且不是一個(gè)請(qǐng)求的時(shí)候,還是會(huì)出現(xiàn)懶加載異常孤钦。比如歧斟,一個(gè)是SSH框架里面的Struts2里面的請(qǐng)求,里面已經(jīng)已經(jīng)通過OpenSessionInViewFilter解決的懶加載異常偏形,但是當(dāng)系統(tǒng)需要的Servlet的監(jiān)聽器里面需要初始化某些數(shù)據(jù)的時(shí)候静袖,而且這些數(shù)據(jù)與其他數(shù)據(jù)有關(guān)系的時(shí)候,還是會(huì)出現(xiàn)懶加載異常俊扭,所以還要在實(shí)體配置文件中配置lazy="false"屬性勾徽。