Hibernate延遲加載和會話關閉的矛盾解決方案

當持久層利用session的load()的方法去查詢數(shù)據(jù)時,返回的只是虛擬代理,此時并沒有真正的發(fā)送sql語句,如果在視圖上使用到查詢的數(shù)據(jù)時,此時sql語句才會真正發(fā)出,但這時候會話已經被關閉,無法在獲取到數(shù)據(jù)。又或者在一對多的關聯(lián)場景下,存在懶加載情況,也會出現(xià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的生命周期就會延長直到視圖渲染完成后才結束session。

存在的問題:
  在高并發(fā)的情況下、影響性能。因為這樣一來,每個從這個過濾器過的請求的session都要被延長生命周期,因為會話上綁定了數(shù)據(jù)庫連接。所以很有可能使數(shù)據(jù)庫連接被某些無用的session占用,導致真正需要連接的會話被阻塞。

二、利用Hibernate工具類的isInitialized方法來解決

以user為例,在控制代碼中,提前初始化視圖上需要用到的數(shù)據(jù):

    /*
     * 利用Hibernate工具類的isInitialized方法,判斷user是否被初始化
     * 是的時候返回true,否則返回false
     * 如果沒有被初始化則用Hibernate工具類的initialize將對象初始化
     */  
if(!Hibernate.isInitialized(user)) {
        Hibernate.initialize(user);
    }

但是這樣的做法就需要我們去對代碼的邏輯做一些修改,并且使方法和hibernate有了一定的耦合。

三、自定義過濾器

和Spring的OpenSessionInViewFilter一樣,我們可以自己定義一個過濾器,來延長會話的生命周期。
拿到SpringIoC容器:

ServletContext sc = requset.getServletContext();
WebApplicationContext ctx = 
            WebApplicationContextUtils.getWebApplicationContext(sc);

從容器中取出Session并在chain.doFilter(request, response);前后分別開啟和關閉會話。這種做法和Spring的OpenSessionInViewFilter沒什么本質區(qū)別。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容