Hibernate查詢、 檢索、 抓取 (Fetch)

1、HQL
在hql中關鍵字不區分大小寫,但屬性和類名區分大小寫

1. 簡單屬性查詢
  * 單一屬性查詢,返回結果集屬性列表
  * 多個屬性查詢,返回集合元素是對象數組,數組長度取決於select中屬性個數
  * 返回數組不夠對象化,能夠採用hql動態實例化對象
    e.g:  select new Student(name, age) from Student;

2. 實體對象查詢
  * N + 1問題,在默認狀況下,使用query.iterate查詢, 可能出現N + 1問題
    發出N+1條sql語句
    1: 首先發出一條查詢id列表的SQL
    N: 根據id列表到緩存中查詢,若是緩存未命中,則根據ID發出N條相應sql
  * list和iterated 區別
    > list :  每次都會發出SQL語句,list會向緩存中放入數據,而不利用緩存的數據
    > iterate :  在默認狀況下iterate利用緩存數據,但在緩存中根據ID未命中則可能出現N+1問題

3. 條件查詢
  * 能夠採用拼接字符串的方式傳遞參數
  * 能夠採用 ?來傳遞參數(索引從0開始)
  * 能夠採用 :參數名 來傳遞

4. 本地SQL查詢
5. 外置命名查詢
6. 分頁查詢
7. 對象導航查詢
9. 鏈接查詢 (內連,外連)
  * 內鏈接
     select c.name, s.name from Student s  join s.classes c
  * 外鏈接(左鏈接/右鏈接)
     left:   select c.name, s.name from Classes c left join c.students s
     right: select c.name, s.name from Classes c right join c.students s

10. 統計查詢
11. DML風格的操做(儘可能少用,由於和緩存不一樣步)


2、 檢索

Order --> Customer
1.  當即檢索策略  lazy="false"

select c from Customer c
若是查詢n個Customer對象,那麼必須執行N+1次select查詢,這種策略沒有利用SQL的鏈接查詢

能夠執行一條左外鏈接查詢全部數據
select * from CUSTOMER left outer join ORDERS on ....

2.  延遲檢索策略
對於<set>元素優先考慮延遲檢索, 設置lazy="true"
Customer對象的orders變量引用集合代理類實例, 當第一次訪問它時,Hibernate會初始化這個集合代理類實例, 在初始化過程當中到數據庫中檢索全部與Customer關聯的Order對象,執行select語句:

select * from ORDERS where CUSTOMER_ID=1;

缺點: 
應用程序若是但願訪問遊離狀態的代理類實例,必須保證它在持久化狀態時已經被初始化

lazy策略能夠用在:

* <class>標籤上:能夠取值true/false
* <property>標籤上,能夠取值true/false,這個特性須要類加強
* <set>/<list>等集合上,能夠取值爲true/false/extra
* <one-to-one>/<many-to-one>等標籤上,能夠取值false/proxy/no-proxy sql

>>  getload的區別: 數據庫

* get不支持延遲加載,而load支持。
* 當查詢特定的數據庫中不存在的數據時,get會返回null,而load則拋出異常。 數組

>>  類(Class)的延遲加載緩存

* 設置<class>標籤中的lazy="true",或是保持默認(即不配置lazy屬性)
* 若是lazy的屬性值爲true,那麼在使用load方法加載數據時,只有確實用到數據的時候纔會發出sql語句;這樣有可能減小系統的開銷。 session

>> 集合(collection)的延遲加載:能夠取值truefalseextra fetch

* true:默認取值,它的意思是隻有在調用這個集合獲取裏面的元素對象時,才發出查詢語句,加載其集合元素的數據
* false:取消懶加載特性,即在加載對象的同時,就發出第二條查詢語句加載其關聯集合的數據
* extra: 推薦使用, 一種比較聰明的懶加載策略,即調用集合的size/contains等方法的時候,hibernate並不會去加載整個集合的數據,而是發出一條聰明的SQL語句,以便得到須要的值,只有在真正須要用到這些集合元素對象數據的時候,纔去發出查詢語句加載全部對象的數據 優化

>> Hibernate單端關聯懶加載策略:即在<one-to-one>/<many-to-one>標籤上能夠配置懶加載策略。能夠取值爲:false/proxy/no-proxy spa

* false: 取消懶加載策略,即在加載對象的同時,發出查詢語句,加載其關聯對象
* proxy: 這是hibernate對單端關聯的默認懶加載策略,即只有在調用到其關聯對象的方法的時候才真正發出查詢語句查詢其對象數據,其關聯對象是代理類
* no-proxy:這種懶加載特性須要對類進行加強,使用no-proxy,其關聯對象不是代理類 hibernate


3.  左外鏈接檢索策略
默認, 在多對一關聯級別使用左外鏈接檢索策略
如: <many-to-one outer-join=「true」 >
Order order = (Order)session.get(Order.class, 1);
Hibernate執行:
select * from ORDERS left outer join CUSTOMERS on ...

***********************************
Hibernate 容許在應用程序中覆蓋映射文件中設定的檢索策略, 由應用程序在運行時決定檢索對象圖的深度.
// 將使用映射文件配置的檢索策略
from Customer as c where c.id=1
// 在HQL中顯示指定左外鏈接檢索關聯的Orders集合, 所以會覆蓋映射文件配置的檢索策略 
from Customer as c  left join fetch c.orders where c.id=1

Hibernate API: SchemaExport  
方法: create
SchemaExport export = new SchemaExport(new Configuration().configure());
export.create(true, true);


3、抓取 fetch
1. 單端代理的批量抓取
實例A引用實例B,B若是是代理的話,若是遍歷A的查詢結果集(假如10條),在遍歷A的時候訪問B變量,將會致使n次查詢語句的發出!這個時候,若是B端的class上配置 batch-size,Hibernate會減小SQL語句的數量
批量抓取是延遲查詢抓取的優化方案:類級別和集合級別

<many-to-one ... fetch="select | join">

A   select:
關聯對象或集合單獨執行SQL查詢
B    join:  
查詢實體使用外鏈接加載關聯的實體或集合,此時 lazy 失效

2. 集合批量抓取
<set ... fetch="select | join | subselect">
select, join 和前面同樣, 隻影響 load / get
subselect , 影響HQL, 單獨發SQL查詢HQL查到的全部實體關聯的每一個集合

4、 批量更新
jdbc fetch size: 每次取多少條數據,須要JDBC和底層數據庫的支持,查詢大量數據時,不會一次性把所有數據讀入內存: hibernate.jdbc.fetch_size建議值50

jdbc batch size: 批量更新,hibernate.jdbc.batch_size建議值30
相關文章
相關標籤/搜索