1. 程式人生 > >Hibernate懶載入常見問題及解決方案

Hibernate懶載入常見問題及解決方案

什麼是懶載入?

懶載入(Load On Demand)是一種獨特而又強大的資料獲取方法,它能夠在使用者滾動頁面的時候自動獲取更多的資料,而新得到的資料不會影響原有資料的顯示,同時最大程度上減少伺服器端的資源耗用。(百度說的)

通俗點,就是在找一個物件時不找出與他關聯的物件,而是在需要相關聯物件(或其屬性)時才去資料庫中找,也稱之為延遲載入。

我們一般通過MyEclipse的逆向工程生成實體類,併為該類自動配置註解,該實體類有一個一對多的屬性,這時hibernate自身提供給我們fetch = FetchType.LAZY這個屬性:

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "standard"
) public Set<Courier> getCouriers() { return this.couriers; }

從程式碼上可以看到,該註解預設設定了延遲載入fetch = FetchType.LAZY。所以當應用程式查詢該實體類對應的表的資料時,出現了以下錯誤:

org.hibernate.LazyInitializationException:could not initialize proxy - no Session
。。。。。省略。。。。。。

這意味著在讀取資料的時候,Session已經關閉。
解決方案一:把FetchType.LAZY設定為EAGER,取消延遲載入機制。(不推薦)

fetch = FetchType.EAGER

解決方案二:在web.xml中新增一個過濾器,這個過濾器必須要位於Struts的核心過濾器之前
(推薦)

< filter>   
    < filter-name>hibernateFilter< /filter-name>   
    < filter-class>   
     org.springframework.orm.hibernate3.support.OpenSessionInViewFilter   
    < /filter-class>   
< /filter
>
< filter-mapping> < filter-name>hibernateFilter< /filter-name> < url-pattern>/*< /url-pattern> < /filter-mapping>

當然了,如果我們用了Spring整合Hibernate JPA,那麼Session就被EntityManager所替換,這時我們推薦使用Spring框架提供過濾器:OpenEntityManagerInViewFilter
該過濾器作用的是,在訪問檢視層(包括Action層)之前開啟session,在訪問結束之後,關閉session

<!-- 必須放在struts2的過濾器之前 -->
<filter>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>