Hibernate懶加載解析

Hibernate懶加載解析java

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

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

   實現懶加載的前提: 緩存

1 實體類不能是final的session

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

一、   經過Session.load()實現懶加載框架

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

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

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

使用load()能夠提升效率,由於剛開始的時候並無查詢數據庫。但不多使用。

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

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

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

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

三、   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的設置將沒有意義.

四、   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同時查詢出來,不會造成屢次查詢。 

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

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

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

三、lazy="true"或lazy="false"fetch = "join",延遲都不會做用,由於採用的是外鏈接查詢,同時把主對象和關聯對象都查詢出來了. 

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

相關文章
相關標籤/搜索