天天看點

懶加載異常 處理方法

     首先看一下什麼是懶加載:

所謂懶加載(lazy)就是延時加載,延遲加載。

什麼時候用懶加載呢,我隻能回答要用懶加載的時候就用懶加載。

至于為什麼要用懶加載呢,就是當我們要通路的資料量過大時,明顯用緩存不太合适,

因為記憶體容量有限 ,為了減少并發量,減少系統資源的消耗,

我們讓資料在需要的時候才進行加載,這時我們就用到了懶加載。

比如部門entity和員工entity,部門與員工1對多,如果lazy設定為 false,那麼隻要加載了一個部門的po,就會根據一對多配置的關系把所有員工的po也加載出來。但是實際上有時候隻是需要用到部門的資訊,不需要用到 員工的資訊,這時員工po的加載就等于浪費資源。如果lazy設定為true,那麼隻有當你通路部門po的員工資訊時候才回去加載員工的po的資訊。

hibernate3.0中lazy有三個值,true,false,proxy,預設的是lazy="proxy".

具體設定成什麼要看你的需求,并不是說哪個設定就是最好的。

假如在student對象中包含一個head對象

如果你确定在用student對象的時候就要用到head對象裡的屬性,那你就設定立即加載,因為設定立即加載那麼在查詢student的同時就會查詢 student的head,hibernate就會在查詢的時候關聯兩張表進而生成的sql就可能隻有一條。而如果你設定的是延遲加載,那麼肯定會要生成 1+n條sql語句:其中“1”是查詢student的語句,“n”是根據n個student的id去查詢head的n條語句。而且,延遲加載是要用到的 時候才去執行查詢,這樣系統判斷那裡需要加載,那裡不需要加載也需要時間,性能上肯定就不如立即加載了!

如果,你是有的地方需要用到student的時候才用到head屬性,那麼你就設定成延遲加載,因為查詢2張表的資料肯定要比查詢1張表的資料消耗大。

到低要怎樣設定就要看你的實際需求了

延遲加載機制是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正需要資料的時候,才真正執行資料加載操作。在hibernate中提供了對實體對象的延遲加載以及對集合的延遲加載,另外在hibernate3中還提供了對屬性的延遲加載。

a、實體對象的延遲加載 

如果想對實體對象使用延遲加載,必須要在實體的映射配置檔案中進行相應的配置,如下所示:

<hibernate-mapping>

 <class name=”com.neusoft.entity.user” table=”user” lazy=”true”>

    ……

 </class>

</hibernate-mapping>

     通過将class的lazy屬性設定為true,來開啟實體的延遲加載特性。如果我們運作下面的代碼:

    user user=(user)session.load(user.class,”1”);(1)

    system.out.println(user.getname());(2)

  當運作到(1)處時,hibernate并沒有發起對資料的查詢,如果此時通過一些調試工具,觀察此時user對象的記憶體快照,會驚奇的發現,此時返 回的可能是user$enhancerbycglib$$bede8986類型的對象,而且其屬性為null,這是怎麼回 事?session.load()方法會傳回實體對象的代理類對象,這裡所傳回的對象類型就是user對象的代理類對象。在hibernate中通過使用 cglib,來實作動态構造一個目标對象的代理類對象,并且在代理類對象中包含目标對象的所有屬性和方法,而且所有屬性均被指派為null。通過調試器顯

示的記憶體快照,可以看出此時真正的user對象,是包含在代理對象的cglib$calback_0.target屬性中,當代碼運作到(2)處時,此時 調用user.getname()方法,這時通過cglib賦予的回調機制,實際上調用cglib$calback_0.getname()方法,當調用 該方法時,hibernate會首先檢查cglib$calback_0.target屬性是否為null,如果不為空,則調用目标對象的getname 方法,如果為空,則會發起資料庫查詢,生成類似這樣的sql語句:select

* from user where id=’1’;來查詢資料,并構造目标對象,并且将它指派到cglib$calback_0.target屬性中。

  這樣,通過一個中間代理對象,hibernate實作了實體的延遲加載,隻有當使用者真正發起獲得實體對象屬性的動作時,才真正會發起資料庫查詢操作。 是以實體的延遲加載是用通過中間代理類完成的,是以隻有session.load()方法才會利用實體延遲加載,因為隻有session.load()方 法才會傳回實體類的代理類對象。

兩種處理方法:

一、這是延時加載的問題,把有關聯的所有pojo類,在hibernate.cfg.xml檔案中。一般在many-to-one中,set标簽内中設lazy="false" 。

二、用opensessioninviewfilter過濾器,注意hibernatefilter過濾器和struts2過濾器在映射時的先後順序。同時要配置事物處理,否則會導緻session處于隻讀狀态而不能做修改、删除的動作。

在web.xml檔案中加入一個filter如下:注意要加載

struts過濾器前面。

作用是攔截".action“結尾的請求,opensessioninviewfilter的作用是将session延時關閉。

懶加載異常 處理方法

在action類中會調用service層的方法,然後調用session.一般當session通路結束之後就會将session關閉.

比如我們要得到user的清單,預設情況下是不會将其中的roles的所有資訊全部查出來的,最多隻給出一個id,或者是name.

但是我們這個時候如果要列印roles的類容,就會報懶加載異常了.因為hibernate根本就沒有将role的資料查出來.

繼續閱讀