Hibernate的檢索方式(五)

轉載自:http://aumy2008.blogbus.com/logs/14096736.html

五、高級查詢技巧

 

2、集合過濾

       延遲檢索策略――customer.getOrders().iterator() (加載關聯對象集合),這種方式的不足:

l         全部加載

l         不能排序

 

2種辦法可以解決上邊不足,一種是通過HQLQBC查詢orders集合,還有一種辦法就是使用集合過濾

 

集合過濾示例:

    List result=session.createFilter(customer.getOrders(),           "where this.price>200 order by this.price").list();    Iterator it=result.iterator();    while(it.hasNext()){       Order order =(Order)it.next();       .....

    }

 

       SessioncreateFilter()方法用來過濾集合,它具有以下特定。

l         返回Qurey類型的實例。

l         第一個參數:指定一個持久化對象的集合,這個集合是否已經被初始化並沒有關係,但它所屬的對象必須處於持久化狀態。否則拋出異常。

l         第二個參數:指定過濾條件,它由合法的HQL查詢語句組成。

l         不管持久化對象的集合是否已經初始化,Querylist()方法都會執行SQL查詢語句,到數據庫中檢索Order對象。

l         如果對象的集合已經被初始化,爲了保證Session的緩存中不會出現OID相同的Order對象,Querylist()方法不會再創建Order對象,僅僅返回已經存在的Order對象的引用。

l         如果沒有初始化,Querylist()方法創建相應的對象,但不會初始化所給對象的集合。(僅僅取出符合條件的對象集合,是對象集合的子集)

 

集合過濾的幾個應用:

A、爲集合排序或設置約束條件

B、 集合分頁

C、 檢索集合中對象的某個屬性

D、檢索數據庫中與Customer對象的orders集合中的Order對象的屬性(一個或多個)相同的所有Order對象

E、 檢索Order對象的lineItems集合中LineItem對象的Item

 

代碼示例:

     List result=session.createFilter(customer.getOrders(),        " order by this.price asc")        .setFirstResult(10)        .setMaxResults(5)        .list();          List result=session.createFilter(customer.getOrders(),        "select this.orderNumber")        .list();          List result=session.createFilter(customer.getOrders(),        "select other from Order other where other.price=this.price")        .list();          List result=session.createFilter(order.getLineItems(),        "select this.item")

        .list();

 

3、子查詢

       HQL支持where子句中嵌入查詢語句。

from Customer c where 1<(select count(o) from c.orders o) ――相關子查詢

from Order o where o.price>(select avg(o1.price) from Order o1)  無關

 

       關於子查詢的用法說明:

       1)、子查詢可以分爲相關子查詢和無關子查詢。

       2)、依賴底層數據庫對子查詢的支持能力。

       3)、如果子查詢語句返回多條記錄,可以用一下關鍵字來衡量。

l         all:表示子查詢語句返回的所有記錄。

l         any:任意一條記錄。

l         some:與“any”等價。

l         in:與“=any”等價。

l         exists:至少返回一條記錄。

例:訂單的價格都不小於100的客戶

from Customer c where 100>all (select o.price from c.orders o)

有一條訂單的價格小於100的客戶

from Customer c where 100>any (select o.price from c.orders o)

有一條訂單的價格等於100的客戶

from Customer c where 100=some (select o.price from c.orders o)

from Customer c where 100=any (select o.price from c.orders o)

from Customer c where 100 in (select o.price from c.orders o)

至少有一條訂單的客戶

from Customer c where exsist (from c.orders)

 

4)、如果子查詢語句查詢的是集合,HQL提供了所寫語法

     Iterator it=session.createQurey(               "from Customer c where :order in element(c.orders)")                  .setEntity("order",order)                  .list()

                  .iterator();

       element(c.orders)等價於(from c.orders

 

       HQL提供了一族操縱集合的函數或者屬性。

l         size()函數或size屬性:獲取集合中元素的數目。

l         minIndex()函數或minIndex屬性:對於建立了索引的集合,獲取最小的索引。

l         maxIndex()函數或maxIndex屬性:對於建立了索引的集合,獲取最大的索引。

l         minElement()函數或minElement屬性:對於包含基本類型元素的集合,獲得集合中取值最小的元素。

l         maxElement()函數或maxElement屬性:對於包含基本類型元素的集合,獲得集合中取值最大的元素。

l         elements()函數:獲得集合中所有元素。

 

如:訂單數目大於零的客戶

from Customer c where c.orders.size>0

或者  from Customer c where size(c.orders)>0

  

4、本地SQL查詢

       Hibernate本地SQL查詢提供了支持,爲了把SQL查詢返回的關係數據映射爲對象,需要在SQL查詢語句中爲字段指定別名。

    String sql1 = "select cs.ID as {c.id},cs.name as {c.name} "           + "from CUSTOMERS cs where cs.ID=1";

    Query query = session.createSQLQurey(sql1, "c", Customer.class);

    String sql1 = "select {c.*} "       + "from CUSTOMERS c where c.ID=1";

    Query query = session.createSQLQurey(sql1, "c", Customer.class);

多個不同的對象情況

String sql1 = "select {c.*},{o.*} from CUSTOMERS c inner join ORDERS o"           + " where c.ID=o.CUSTOMER_ID";    Query query = session.createSQLQurey(sql1, new String[] { "c", "o" },

           new Class[] { Customer.class, Order.class });

 

       在程序中嵌入本地SQL語句會增加維護程序代碼的難度,如果數據庫表的結構發生變化,必須修改相應的程序代碼,因此更合理的方式是把SQL查詢語句放到映射文件中:

    <sql-query name="findCustomersAndOrders"><![CDATA[         select {c.*},{o.*} from CUSTOMERS c inner join ORDERS o           where c.ID=o.CUSTOMER_ID                                              ]]>       <return alias="c"class="Customer">       <return alias="o"class="Order">

    </sql-query>

  

六、查詢性能優化

1、  降低訪問數據庫的頻率,減少select語句的數目。實現手段包括:

l         使用迫切左外連接或迫切內連接檢索策略。

l         對延遲加載或立即加載策略設置批量檢索數目。

l         使用查詢緩存。

2、避免多餘加載程序不需要訪問的數據。實現手段包括:

l         使用延遲檢索策略。

l         使用集合過濾。

3、  避免報表查詢數據佔用緩存。實現手段爲利用投影查詢功能,查詢出實體的部分屬性。

4、減少select語句中的字段,從而降低訪問數據庫的數據量。實現手段爲利用Queryiterate()方法。

  

iterate()方法:

       Query接口的iterate()方法和list()方法都能執行SQL查詢語句。

       list()首先檢索ID字段,然後根據ID字段到Hibernate第一緩存以及第二級緩存中查找匹配的對象,如果存在,就直接把它加入到查詢結果集中,否則就只想額外的select語句,根據ID字段數據庫中檢索該對象。

 

查詢緩存

       查詢緩存適應以下場合:

l         在應用程序運行時經常使用的查詢語句。

l         很少對與查詢語句關聯的數據庫數據進行插入、刪除或更新操作。

 

查詢語句啓用查詢緩存的步驟如下:

A、配置第二級緩存。

B、 Hibernatehibernate.properties配置文件中設置查詢緩存屬性:

hibernate.cache.use_query_cache=true

       C、啓用查詢緩存。調用Query接口的setCacheable(true)方法。

 結束!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章