淺析Hibernate實現實體對象延遲加載
學習Hibernate時,經常會遇到實體對象延遲加載問題,這里將介紹問題的解決方法Hibernate實現實體對象延遲加載。
延遲加載機制是為了避免一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正需要數據的時候,才真正執行數據加載操作。在Hibernate中提供了對實體對象的延遲加載以及對集合的延遲加載,另外在Hibernate3中還提供了對屬性的延遲加載。下面我們就分別介紹這些種類的延遲加載的細節。
Hibernate實現實體對象延遲加載:
如果想Hibernate實現實體對象延遲加載,必須要在實體的映射配置文件中進行相應的配置,如下所示:
- <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”);
- System.out.println(user.getName());
當運行到第一條時,Hibernate并沒有發起對數據的查詢,如果我們此時通過一些調試工具(比如JBuilder2005的Debug工具),觀察此時user對象的內存快照,我們會驚奇的發現,此時返回的可能是 User$EnhancerByCGLIB$$bede8986類型的對象,而且其屬性為null,這是怎么回事?還記得前面我曾講過session.load()方法,會返回實體對象的代理類對象,這里所返回的對象類型就是User對象的代理類對象。在Hibernate中通過使用CGLIB,來實現動態構造一個目標對象的代理類對象,并且在代理類對象中包含目標對象的所有屬性和方法,而且所有屬性均被賦值為null。通過調試器顯示的內存快照,我們可以看出此時真正的User對象,是包含在代理對象的CGLIB$CALBACK_0.target屬性中,當代碼運行到第二條時,此時調用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()方法才會返回實體類的代理類對象。
【編輯推薦】