當持久層利用session的load()的方法去查詢數(shù)據(jù)時寿谴,返回的只是虛擬代理,此時并沒有真正的發(fā)送sql語句,如果在視圖上使用到查詢的數(shù)據(jù)時离福,此時sql語句才會真正發(fā)出,但這時候會話已經(jīng)被關(guān)閉炼蛤,無法在獲取到數(shù)據(jù)妖爷。又或者在一對多的關(guān)聯(lián)場景下,存在懶加載情況理朋,也會出現(xiàn)延遲加載和會話關(guān)閉的矛盾絮识。
一、利用Spring的OpenSessionInViewFilter過濾器延長會話的生命周期
web.xml中配置過濾器
<filter>
<filter-name>osiv</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>osiv</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
配置完過濾器后嗽上,session的生命周期就會延長直到視圖渲染完成后才結(jié)束session次舌。
存在的問題:
在高并發(fā)的情況下、影響性能兽愤。因為這樣一來彼念,每個從這個過濾器過的請求的session都要被延長生命周期,因為會話上綁定了數(shù)據(jù)庫連接浅萧。所以很有可能使數(shù)據(jù)庫連接被某些無用的session占用逐沙,導(dǎo)致真正需要連接的會話被阻塞。
二洼畅、利用Hibernate工具類的isInitialized方法來解決
以user為例吩案,在控制代碼中,提前初始化視圖上需要用到的數(shù)據(jù):
/*
* 利用Hibernate工具類的isInitialized方法帝簇,判斷user是否被初始化
* 是的時候返回true徘郭,否則返回false
* 如果沒有被初始化則用Hibernate工具類的initialize將對象初始化
*/
if(!Hibernate.isInitialized(user)) {
Hibernate.initialize(user);
}
但是這樣的做法就需要我們?nèi)Υa的邏輯做一些修改靠益,并且使方法和hibernate有了一定的耦合。
三残揉、自定義過濾器
和Spring的OpenSessionInViewFilter一樣胧后,我們可以自己定義一個過濾器,來延長會話的生命周期抱环。
拿到SpringIoC容器:
ServletContext sc = requset.getServletContext();
WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(sc);
從容器中取出Session并在chain.doFilter(request, response);前后分別開啟和關(guān)閉會話绩卤。這種做法和Spring的OpenSessionInViewFilter沒什么本質(zhì)區(qū)別。