hibernate的lazy的使用
引用:https://blog.csdn.net/Vincent_yuan1991/article/details/53482487
一:
lazy,延遲加載
Lazy的有效期:只有在session打開的時候才有效;session關閉后lazy就沒效了。
lazy策略可以用在:
- 標簽上:可以取值true/false
- 標簽上,可以取值true/false,這個特性需要類增強
- /等集合上,可以取值為true/false/extra
- /等標簽上,可以取值false/proxy/no-proxy
6.1 get和load的區別: - get不支持延遲加載,而load支持。
- 當查詢特定的數據庫中不存在的數據時,get會返回null,而load則拋出異常。
6.2 類(Class)的延遲加載: - 設置標簽中的lazy=“true”,或是保持默認(即不配置lazy屬性)
- 如果lazy的屬性值為true,那么在使用load方法加載數據時,只有確實用到數據的時候才會發出sql語句;這樣有可能減少系統的開銷。
- //不會發出查詢sql
System.out.println(“group id=” + group.getId());
這里有一個問題,為什么加載主鍵的時候不需要發出sql語句。
6.3 集合(collection)的延遲加載:可以取值true,false,extra - 保持集合上的lazy的默認值,此時的效果和lazy="extra"是基本一樣的。
- 設置集合上的lazy=extra,此時的效果和lazy屬性的默認值是基本一樣的。但是推薦使用這個屬性值,因為在統計時這種情況顯得比較智能。當然延遲是有效果的。
- 設置集合上的lazy=false
true:默認取值,它的意思是只有在調用這個集合獲取里面的元素對象時,才發出查詢語句,加載其集合元素的數據
false:取消懶加載特性,即在加載對象的同時,就發出第二條查詢語句加載其關聯集合的數據
extra:一種比較聰明的懶加載策略,即調用集合的size/contains等方法的時候,hibernate
并不會去加載整個集合的數據,而是發出一條聰明的SQL語句,以便獲得需要的值,只有在真正需要用到這些集合元素對象數據的時候,才去發出查詢語句加載所有對象的數據
6.4 Hibernate單端關聯懶加載策略:即在/標簽上可以配置
懶加載策略。可以取值為:false/proxy/no-proxy
false:取消懶加載策略,即在加載對象的同時,發出查詢語句,加載其關聯對象
proxy:這是hibernate對單端關聯的默認懶加載策略,即只有在調用到其關聯對象的方法的時候才真正發出查詢語句查詢其對象數據,其關聯對象是代理類
no-proxy:這種懶加載特性需要對類進行增強,使用no-proxy,其關聯對象不是代理類
注意:在class標簽上配置的lazy屬性不會影響到關聯對象!!!
二:
a
懶加載可以提高性能嗎?
不可以簡單的說"能",因為Hibernate的關系映射拖累了SQL的性能,所以想出懶加載來彌補.只是彌補而以,不會超越.所以大家不要想著使用了懶加載總體性能就提高了,其實總體性能不下降就萬幸了.
Hibernate的lazy屬性可以配置在:
(常用)標簽上 ,可以取值true,false,extra
默認為true,當為true時,會懶加載,訪問集合屬性時再發出SQL語句.但set.size()時,很不智能,不會生成count()語句,而是查出所有記錄賦值給set.
extra說明:調用集合的set.size()時,會生成select count(*)from tableName,比較智能.建議使用
(少用)標簽上 ,可以取值false,proxy,noproxy
當為true時,會有懶加載特性,當為false時會產生N+1問題,比如一個學生對應一個班級,用一條SQL查出10個學生,當訪問學生的班級屬性時Hibernate會再產生10條SQL分別查出每個學生對應的班級.
(不用)標簽上 ,可以取值true,false
默認為true,當為false時,load()方法將失去懶加載的特性與get()一樣,不影響集合()標簽上的lazy特性
(不用)標簽上 ,可以取值true,false
默認值為false,懶加載某個字段,無意義,不要使用
get()與load()的區別
get()無懶加載特性,馬上執行SQL查詢.
load()有懶加載特性,會返加一個代理對象,所以永遠不為null,先不執行SQL,要取對象的值時才執行SQL語句,前題session不能關閉,標簽上lazy不為false.
實現懶加載的前提: 1 PO不能是final的
2 能實現懶加載的對象(PO)都是被CGLIB改寫的代理對象,所以不能是final修飾的
3 須要asm,cglib兩個jar包
4 相應的lazy屬性為true
5 相應的fetch屬性為select
什么時候出遇到懶加載
1 使用load()
2 一對一
查主對象 默認使用join連接,不會發生懶加載
查從對象 默認會發生懶加載,先執行一句select查出從對象,當通過從對象訪問了主對象時,再執行一句select查出主對象.
3 多對一
在使用hbm.xnl時,取多的一方時,默認會懶加載,不取一的一方
在使用JPA時,取多的一方時,默認自動使用join on語句取出一的一方(用戶與組,用戶是多的一方,組是一的一方)
4 一對多()
默認會懶加載,這是必須的,是重常用的。
實現懶加載的方案:
方法一:(沒有使用懶加載)
用 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方式,是left outer 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中無效。
總結
以上是生活随笔為你收集整理的hibernate的lazy的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate框架(1)
- 下一篇: 遍历HashMap的四种方法