Hibernate延遲加載
小編:管理員 437閱讀 2022.09.14
前言:
上一篇文章我們學習了Hibernate的多表關聯關系,這里就涉及到一個很實用的概念:延遲加載或者也叫惰性加載,懶加載。使用延遲加載可以提高程序的運行效率。Java程序與數據庫交互的頻次越低,程序運行效率越高,所以我們應該盡量減少Java程序與數據庫的交互次數,Hibernate延遲加載就很好的做到了這一點。
通過一個具體的業務場景來理解延遲加載:
客戶(Customer)和訂單(Orders),當我們查詢Customer對象時,因為有級聯關系,所以會將對應的Orders對象一并查詢出來,這樣就需要發送兩條SQL語句,分別查詢customer表和orders表中的數據。延遲加載的思路是:當我們查詢Customer的時候,如果沒有調用orders,則只發送了一條SQL語句查詢customer;如果需要調用orders,則發送兩條SQL語句查詢customer和orders。所以延遲加載可以看做是一種優化機制,根據具體的代碼,自動選擇發送的SQL語句條數。
代碼:
理解了延遲加載的概念,接下來就是如何使用了。
延遲加載使用起來很簡單,直接在實體關系映射文件中進行配置即可。
一對多:
1.查詢Customer,對orders進行延遲加載設置,在customer.hbm.xml進行設置,延遲加載默認為開啟狀態。
復制
所以查詢Customer,如果不調用orders,則會看到只發送一條SQL。

當調用orders的時候,發送兩條SQL。

現在將延遲加載關閉,customer.hbm.xml中將set標簽的lazy屬性改為false。
復制
現在繼續查詢Customer,可以看到,即使沒有調用orders屬性,也同樣發送了兩條SQL,即延遲加載已經關閉,立即加載orders對象。

lazy屬性除了可以設置true和false,還可設置extra,extra是比true更加懶惰的一種加載方式,或者說更加智能的一種加載方式,通過一個例子來理解兩者的區別:
查詢出Customer對象,然后需要打印該對象對應的orders集合的長度,使用lazy="true"。

會看到查詢了兩次SQL,第二次SQL首先將orders表中的記錄查詢出來,然后將這些記錄映射成對象,創建Set集合對象,將oreders對象放入集合對象中,然后返回集合對象的長度,這是它的流程。
若將設置改為lazy="extra",會看到這樣的SQL語句。
復制

同樣是兩次SQL語句,第一次SQL沒有區別。
此時第二次SQL語句是使用聚會函數來統計orders的總記錄數,最終將結果2返回,與上面的操作接收到的結果是一樣的。
但是很顯然,這種方式更加高效,因為SQL直接統計了記錄數然后返回,省去了查出記錄--封裝對象--放入集合--返回集合長度這一復雜的流程。
所以,通過這個例子我們可以看出,extra是更高效的一種加載方式,不到需要加載數據庫具體數值的時候,是不會直接查詢記錄的。
這是通過Customer來設置orders的延遲加載,同理,我們也可以通過Orders來設置customer的延遲加載。
在orders.hbm.xml中進行設置。默認值為false,即關閉延遲加載。
復制
所以,查詢Orders時,會發送兩次SQL語句分別查詢Orders以及級聯的Customer。

現在將lazy的值進行修改,這個時候會發現,lazy的值不能改為true,可供我們選擇的只有false proxy no-proxy。

其實這里的proxy和no-proxy是將開啟延遲加載又進行了細分:
設置為no-proxy,當調用方法需要訪問customer的成員變量時,發送SQL語句查詢Customer,否則不發送。
設置為proxy,無論調用的方式是否需要訪問customer的成員變量,都會發送SQL查詢Customer。
這是兩者的區別,但是在使用時,no-proxy編譯時需要進行字節碼增強操作,否則作用和proxy是一樣的。
多對多:
查詢Classes,加載對應的Student,默認延遲加載是開啟的,在classes.hbm.xml中進行設置。
復制
所以查詢Classes,從控制臺看到只發送了一次SQL語句。

當調用Classes的students屬性時,發送兩次SQL。

現在將lazy改為false。
復制
可以看到沒有調用students屬性,依然發送了兩次SQL。

同理,lazy的第三個可選值extra與一對多關系是一樣的,是比true更加懶惰的加載方式。
獲取Student,調用classes也是同樣的配置,在student.hbm.xml中進行配置即可。
總結:
Hibernate延遲加載的配置有很多種方式,都是通過給標簽設置lazy屬性完來完成,并且不同的標簽lazy屬性的值是不一樣的,重點還是理清楚實體類之間的關聯關系,才可以通過設置lazy屬性實現優化代碼效率的目的。
相關推薦
- 經典筆試題-JDBC及Hibernate篇 五、JDBC 及Hibernate:(共12 題:基礎10 道,中等難度2 道)110、數據庫,比如100 用戶同時來訪,要采取什么技術解決?【基礎】 答:可采用連接池。111、什么是ORM?【基礎】 答:對象關系映射(Object—Relational Mapping,簡稱ORM)是一種為了解決面向對象…
- Hibernate Criterion 在查詢方法設計上能夠靈活的依據Criteria的特點來方便地進行查詢條件的組裝.Hibernate設計了CriteriaSpecification作為Criteria的父接口,以下提供了Criteria和DetachedCriteria.Criteria和DetachedCriteria的主要差別在于創建的形式不一樣,Criteria是在線的,所…