Hibernate懶加載解析

Hibernate懶加載解析

在Hibernate框架中,當我們要訪問的數據量過大時,明顯用緩存不太合適, 因爲內存容量有限 ,爲了減少併發量,減少系統資源的消耗,這時Hibernate用懶加載機制來彌補這種缺陷,但是這只是彌補而不是用了懶加載總體性能就提高了。

我們所說的懶加載也被稱爲延遲加載,它在查詢的時候不會立刻訪問數據庫,而是返回代理對象,當真正去使用對象的時候纔會訪問數據庫。

實現懶加載的前提:

1 實體類不能是final的

2 能實現懶加載的對象都是被CGLIB(反射調用)改寫的代理對象,所以不能是final修飾的
3 須要asm,cglib兩個jar包
4 相應的lazy屬性爲true
5 相應的fetch屬性爲select
下面幾種可以實現懶加載功能:

1、   通過Session.load()實現懶加載

load(Object, Serializable):根據id查詢 。查詢返回的是代理對象,不會立刻訪問數據庫,是懶加載的。當真正去使用對象的時候纔會訪問數據庫。

用load()的時候會發現不會打印出查詢語句,而使用get()的時候會打印出查詢語句。

使用load()時如果在session關閉之後再查詢此對象,會報異常:could not initialize proxy - no Session。處理辦法:在session關閉之前初始化一下查詢出來的對象:Hibernate.initialize(user);

使用load()可以提高效率,因爲剛開始的時候並沒有查詢數據庫。但很少使用。

2、   one-to-one(元素)實現了懶加載。

在一對一的時候,查詢主對象時默認不是懶加載。即:查詢主對象的時候也會把從對象查詢出來。

需要把主對象配製成lazy="true" constrained="true"  fetch="select"。此時查詢主對象的時候就不會查詢從對象,從而實現了懶加載。

一對一的時候,查詢從對象的是默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。而是查詢出來的是主對象的代理對象。

3、   many-to-one(元素)實現了懶加載。

多對一的時候,查詢主對象時默認是懶加載。即:查詢主對象的時候不會把從對象查詢出來。

多對一的時候,查詢從對象時默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。

hibernate3.0中lazy有三個值,true,false,proxy,默認的是lazy="proxy".具體設置成什麼要看你的需求,並不是說哪個設置就是最好的。在<many-to-one>與<one-to-one>標籤上:當爲true時,會有懶加載特性,當爲false時會產生N+1問題,比如一個學生對應一個班級,用一條SQL查出10個學生,當訪問學生的班級屬性時Hibernate會再產生10條SQL分別查出每個學生對應的班級.

lazy= 什麼時候捉取

fetch= 捉取方式:select=關聯查詢;join=連接表的方式查詢(效率高)

fetch=join時,lazy的設置將沒有意義.

4、   one-to-many(元素)懶加載:默認會懶加載,這是必須的,是重常用的。

一對多的時候,查詢主對象時默認是懶加載。即:查詢主對象的時候不會把從對象查詢出來。

一對多的時候,查詢從對象時默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。

需要配置主對象中的set集合lazy="false" 這樣就配置成是不懶加載了。或者配置抓取方式fetch="join"也可以變成不懶加載。

實現懶加載的方案:

方法一:(沒有使用懶加載)  

用 Hibernate.initialize(de.getEmps()) 提前加載一下.
方法二:

把與Session脫離的對象重新綁定

lock()方法是用來讓應用程序把一個未修改的對象重新關聯到新session的方法。

//直接重新關聯

session.lock(fritz,LockMode.NONE);

//進行版本檢查後關聯

session.lock(izi,LockMode.READ);

//使用SELECT... FOR UPDATE進行版本檢查後關聯

session.lock(pk,LockMode.UPGRADE);

方法三:

OpenSessionInView

參見 http://www.javaeye.com/topic/32001          

fetch 和 lazy 配置用於數據的查詢

lazy 參數值常見有 false 和 true,Hibernate3映射文件中默認lazy = true ;

fetch 指定了關聯對象抓取的方式,參數值常見是select和join,默認是select,select方式先查詢主對象,再根據關聯外鍵,每一個對象發一個select查詢,獲取關聯的對象,形成了n+1次查詢;而join方式,是leftouter join查詢,主對象和關聯對象用一句外鍵關聯的sql同時查詢出來,不會形成多次查詢。

在映射文件中,不同的組合會使用不同的查詢:

1、lazy="true" fetch = "select" ,使用延遲策略,開始只查詢出主對象,關聯對象不會查詢,只有當用到的時候纔會發出sql語句去查詢 ;

2、lazy="false" fetch = "select" ,沒有用延遲策略,同時查詢出主對象和關聯對象,產生1+n條sql.

3、lazy="true"或lazy="false"fetch = "join",延遲都不會作用,因爲採用的是外連接查詢,同時把主對象和關聯對象都查詢出來了.

另 外,在hql查詢中,配置文件中設置的join方式是不起作用的,而在其他查詢方式如get、criteria等是有效的,使用 select方式;除非在hql中指定join fetch某個關聯對象。fetch策略用於get/load一個對象時,如何獲取非lazy的對象/集合。 這些參數在Query中無效。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章