1. 程式人生 > >hibernate懶載入(lazy載入)

hibernate懶載入(lazy載入)

    所謂懶載入(lazy)就是延時載入,延遲載入。當兩個及以上表使用hibernate來管理級聯關係時,一個表被載入到jvm記憶體時,其相關表可以暫存在資料庫的快取中,當需要使用相關表資料時在載入到jvm記憶體中,通過懶載入機制可以減少記憶體中不必要的開銷,以提高程式的效能。

    需要注意的是,當使用懶載入時,如果將session關閉,則斷開了與資料庫的連線,此時如果要訪問子表資料,由於子表資料是存放在資料庫的快取中,而連線已經關閉,則訪問子表資料會丟擲LazyInitializationException異常。

     解決方法:

    1)不使用懶載入:將子表配置檔案中lazy屬性改為false,對某一個級聯關係不使用懶載入

     <many-to-one name="parent" class="ParrentClass" column="parentId" lazy="false"></many-to-one>  

    注:對於many-to-many同樣適用

    或者將整個子表設定為對任何父表都不使用懶載入,則對整個子表都不使用懶載入

    <class name="ChildClass" table="childTable" lazy="false">

    2)使用過濾器,把close Session這一步推遲到得到頁面結果後執行。這裡可以採用spring中OpenSessionInViewFilter(這是一個過濾器)來實現。

    在web.xml中加入配置

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

    3)手動將需要的子表資料從資料庫快取載入到jvm記憶體中。例如Classroom與Student實體類存在一對多關係(多對多同樣適用),即

public Classroom {

    private Set<Student> students;

    .........

}

dao層有

List<ClassRoom> list = session獲得結果集操作

for (Classroom classroom : list)  {
    Hibernate.initialize(classroom.getStudents()); //迴圈將classroom實體對應的Student集合patch到jvm記憶體中

}

session.close();

方法比較:第一種方法簡單粗暴,優點是不必太在意延遲載入異常,因為不會發生,缺點是每次都將所有相關資料載入到jvm記憶體中,消耗記憶體資源;第二種方法是javaweb中常用的方法,優點是根據需要合理確定載入時間以及是否載入,缺點是隻能用在J2EE中,對於J2SE專案則不適用;第三種方法,優點是靈活掌控何時載入,缺點是增加額外程式碼,並且需要載入子表資料但是忘記在session關閉前將其拉入jvm記憶體中時,會丟擲LazyInitializationException