【java】itoo项目实战之hibernate 懒载入优化性能
? ? ??在做itoo 3.0 的時候,考評系統想要上線,就開始導入數據了,僅僅導入學生2萬條數據,可是導入的速度特別的慢。這個慢的原因是由于導入的時候進行了過多的IO操作。可是導入成功之后,查詢學生的速度更加慢。由于底層用了hibernate的hql語句進行查詢的,學習過hibernate的人都知道,假設hibernate不設置懶載入的話,僅僅有是有關聯的數據都會一次性所有都查詢出來,我試了試。查詢2萬條數據,最深的級聯查詢是有5層,然后發出來的語句是460條,時間大概是10s。然后就考慮使用lazy進行優化。然后就開始對lazy進行了一個研究。
問:懶載入能夠提高性能嗎??
? ? ??不能夠簡單的說"能",由于Hibernate的關系映射拖累了SQL的性能,所以想出懶載入來彌補.僅僅是彌補而以,不會超越.所以大家不要想著使用了懶載入整體性能就提高了,事實上整體性能不下降就萬幸了.
?
問:Hibernate的lazy屬性能夠配置在哪里?
(經常使用)<set><list>標簽上?,能夠取值true,false,extra默覺得true,當為true時,會懶載入,訪問集合屬性時再發出SQL語句.但set.size()時,非常不智能,不會生成count()語句,而是查出全部記錄賦值給set.
extra說明:調用集合的set.size()時,會生成selectcount(*)from tableName,比較智能.建議使用
(少用)<many-to-one><one-to-one>標簽上?,能夠取值false,proxy,noproxy?當為true時,會有懶載入特性,當為false時會產生N+1問題,比方一個學生相應一個班級,用一條SQL查出10個學生,當訪問學生的班級屬性時Hibernate會再產生10條SQL分別查出每一個學生相應的班級.
(不用)<class>標簽上?,能夠取值true,false?默覺得true,當為false時,load()方法將失去懶載入的特性與get()一樣,不影響集合(<set><list>)標簽上的lazy特性
(不用)<property>標簽上?,能夠取值true,false??默認值為false,懶載入某個字段,無意義,不要使用
?
?
問:get()與load()的差別?
get()無懶載入特性,立即運行SQL查詢.
load()有懶載入特性,會返加一個代理對象,所以永遠不為null,先不運行SQL,要取對象的值時才運行SQL語句,前題session不能關閉,<class>標簽上lazy不為false.
?
問:使用懶載入的條件
1 PO不能是final的
2能實現懶載入的對象(PO)都是被CGLIB改寫的代理對象,所以不能是final修飾的
3需要asm,cglib兩個jar包
4對應的lazy屬性為true
5 對應的fetch屬性為select?
?
問:什么時候遇到懶載入
1 使用load()
2 一對一<one-to-one>?
查主對象默認使用join連接,不會發生懶載入
查從對象默認會發生懶載入,先運行一句select查出從對象,當通過從對象訪問了主對象時,再運行一句select查出主對象.
?
3多對一<many-to-one>
在使用hbm.xnl時,取多的一方時,默認會懶載入。不取一的一方
在使用JPA時,取多的一方時,默認自己主動使用joinon語句取出一的一方(用戶與組,用戶是多的一方,組是一的一方)
?
4一對多(<set><list>)
默認會懶載入。這是必須的。是重經常使用的。
?
問:實現懶載入的方案有哪些?
方法一:(沒有使用懶載入)???
用 Hibernate.initialize(de.getEmps()) 提前載入一下.?
?
方法二:
把與Session脫離的對象又一次綁定
lock()方法是用來讓應用程序把一個未改動的對象又一次關聯到新session的方法。
//直接又一次關聯
ssion.lock(fritz,LockMode.NONE);
//進行版本號檢查后關聯
session.lock(izi,LockMode.READ);
//使用SELECT ... FORUPDATE進行版本號檢查后關聯
session.lock(pk,LockMode.UPGRADE);
?
方法三:
OpenSessionInView
OpenSessionInViewFilter是Spring提供的一個針對Hibernate的一個支持類,其主要意思是在發起一個頁面請求時打開Hibernate的Session,一直保持這個Session。直到這個請求結束,詳細是通過一個Filter來實現的。
?
因為Hibernate引入了LazyLoad特性。使得脫離Hibernate的Session周期的對象假設再想通過getter方法取到其關聯對象的值。Hibernate會拋出一個LazyLoad的Exception。所以為了解決問題,Spring引入了這個Filter,使得Hibernate的Session的生命周期變長。
?
詳細參考:http://www.iteye.com/topic/32001
?
問:fetch 和lazy 配置怎樣用于數據的查詢
lazy 參數值常見有 false 和 true,Hibernate3 映射文件里默認lazy = true ;?
?
fetch 指定了關聯對象抓取的方式。參數值常見是select和join,默認是select,select方式先查詢主對象。再依據關聯外鍵,每個對象發一個select查詢。獲取關聯的對象。形成了n+1次查詢。而join方式,是left outerjoin查詢,主對象和關聯對象用一句外鍵關聯的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中無效。
?
? ? ? 最后由于前端框架使用的是easyui,綁定數據的時候,后臺的數據須要轉換成為json串,使用懶載入的話。級聯查詢數據在轉換的時候就會出問題。所以UI后就把懶載入的方式舍棄了,下一節未大家介紹還有一種方式優化。
轉載于:https://www.cnblogs.com/liguangsunls/p/6821313.html
總結
以上是生活随笔為你收集整理的【java】itoo项目实战之hibernate 懒载入优化性能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: elasticsearch 运行原理
- 下一篇: 决策实验(1)——分钱任务