程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Hibernate —— 檢索策略,hibernate檢索策略

Hibernate —— 檢索策略,hibernate檢索策略

編輯:JAVA綜合教程

Hibernate —— 檢索策略,hibernate檢索策略


一、Hibernate 的檢索策略本質上是為了優化 Hibernate 性能。

二、Hibernate 檢索策略包括類級別的檢索策略、和關聯級別的檢索策略(<set> 元素)

三、類級別的檢索策略

1. 立即檢索、延遲檢索

2. 通過 <class> 節點的 lazy 屬性來控制。默認為 true,即為延遲檢索。

3. 只針對 session 的 load() 方法生效。

默認情況下,通過 load() 方法獲取到的對象是一個代理對象,Hibernate 創建代理對象時,僅會初始化 OID。

在第一次訪問非 OID 屬性時,Hibernate 會初始化代理類實例。

4.測試

(1)<class> 的 lazy 屬性為 true

@Test
public void testStrategyClassLevel() {
    Customer customer = (Customer) session.load(Customer.class, 5);
    System.out.println(customer.getClass());
    System.out.println(customer.getCustomerId());
    System.out.println("--------------");
    System.out.println(customer.getCustomerName());
}
class com.nucsoft.strategy.many2one.Customer_$$_javassist_0
5
--------------
Hibernate: 
    select
        customer0_.customer_id as customer1_2_0_,
        customer0_.customer_name as customer2_2_0_ 
    from
        hibernate.customer customer0_ 
    where
        customer0_.customer_id=?
bb

(2)<class> 的 lazy 屬性為 false

@Test
public void testStrategyClassLevel() {
    session.load(Customer.class, 5);
}
Hibernate: 
    select
        customer0_.customer_id as customer1_2_0_,
        customer0_.customer_name as customer2_2_0_ 
    from
        hibernate.customer customer0_ 
    where
        customer0_.customer_id=?

四、關聯級別的檢索策略

1. 指的是用 <set> 元素來配置的多對一和多對多的關聯關系。

2. 主要指的是 <set> 元素的三個屬性:lazy 、fetch、batch-size。

3. lazy 屬性(默認為 true,即采用延遲檢索策略)

(1)決定集合被初始化的時機。

(2)取值為 true 時

  • Hibernate 會在以下情況下初始化集合代理類實例
    • 訪問集合屬性、iterator()、size()、isEmpty()、contains() 等方法時
    • 通過 Hibernate.initialize() 靜態方法顯示的初始化  

(3)取值為 false 時

(4)取值為 extra 時(增強的延遲檢索策略),會盡可能的延遲初始化集合的時機。如:

@Test
public void testSetLazy() {
    Category category = (Category) session.get(Category.class, 5);
    System.out.println(category.getItems().size());
}
Hibernate: 
    select
        category0_.category_id as category1_1_0_,
        category0_.category_name as category2_1_0_ 
    from
        hibernate.category category0_ 
    where
        category0_.category_id=?
Hibernate: 
    select
        count(item_id) 
    from
        hibernate.categories_items 
    where
        category_id =?
2

調用集合的 size() 方法時,是通過 count() 來查詢的。

當調用集合的 iterator() 方法時,會初始化集合。

4. fetch 屬性(默認為 "select")

(1)取值為 "select" 或 "subselect" 時,決定初始化集合查詢語句的形式。

(2)取值為 "join",則決定初始化集合的時機。會忽略 "lazy" 屬性。

(3)測試

<1>取值為 "select" 

@Test
public void testSetLazy() {
    List<Category> categories = session.createQuery("from Category").list();

    for(Category category : categories) {
        System.out.println(category.getItems().size());
    }

}
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_name as customer2_2_ 
    from
        hibernate.customer customer0_
Hibernate: 
    select
        orders0_.customer_id as customer3_2_1_,
        orders0_.order_id as order1_4_1_,
        orders0_.order_id as order1_4_0_,
        orders0_.order_name as order2_4_0_,
        orders0_.customer_id as customer3_4_0_ 
    from
        hibernate.order orders0_ 
    where
        orders0_.customer_id=?
2
Hibernate: 
    select
        orders0_.customer_id as customer3_2_1_,
        orders0_.order_id as order1_4_1_,
        orders0_.order_id as order1_4_0_,
        orders0_.order_name as order2_4_0_,
        orders0_.customer_id as customer3_4_0_ 
    from
        hibernate.order orders0_ 
    where
        orders0_.customer_id=?
2
Hibernate: 
    select
        orders0_.customer_id as customer3_2_1_,
        orders0_.order_id as order1_4_1_,
        orders0_.order_id as order1_4_0_,
        orders0_.order_name as order2_4_0_,
        orders0_.customer_id as customer3_4_0_ 
    from
        hibernate.order orders0_ 
    where
        orders0_.customer_id=?
2
Hibernate: 
    select
        orders0_.customer_id as customer3_2_1_,
        orders0_.order_id as order1_4_1_,
        orders0_.order_id as order1_4_0_,
        orders0_.order_name as order2_4_0_,
        orders0_.customer_id as customer3_4_0_ 
    from
        hibernate.order orders0_ 
    where
        orders0_.customer_id=?
2

<2>取值為 "subselect",會忽略 batch-size 屬性。

Hibernate: 
    select
        category0_.category_id as category1_1_,
        category0_.category_name as category2_1_ 
    from
        hibernate.category category0_
Hibernate: 
    select
        items0_.category_id as category1_1_1_,
        items0_.item_id as item2_0_1_,
        item1_.item_id as item1_3_0_,
        item1_.item_name as item2_3_0_ 
    from
        hibernate.categories_items items0_ 
    inner join
        hibernate.item item1_ 
            on items0_.item_id=item1_.item_id 
    where
        items0_.category_id in (
            ?, ?
        )
2
2
Hibernate: 
    select
        customer0_.customer_id as customer1_2_,
        customer0_.customer_name as customer2_2_ 
    from
        hibernate.customer customer0_
Hibernate: 
    select
        orders0_.customer_id as customer3_2_1_,
        orders0_.order_id as order1_4_1_,
        orders0_.order_id as order1_4_0_,
        orders0_.order_name as order2_4_0_,
        orders0_.customer_id as customer3_4_0_ 
    from
        hibernate.order orders0_ 
    where
        orders0_.customer_id in (
            select
                customer0_.customer_id 
            from
                hibernate.customer customer0_
        )
2
2
2
2

通過子查詢的方式,通過 in 的方式。

<3>取值為 "join"

  • 會采用迫切左外鏈接(使用左外鏈接進行查詢,同時初始化集合屬性)策略來初始化所有關聯的對象
  • lazy 屬性將會被忽略
  • Query 的 list() 方法會忽略這個取值,不會忽略 lazy 屬性。
  • HQL 會忽略取值為 "join" 的取值
@Test
public void testFetch() {
    session.get(Customer.class, 5);
}
Hibernate: 
    select
        customer0_.customer_id as customer1_2_1_,
        customer0_.customer_name as customer2_2_1_,
        orders1_.customer_id as customer3_2_3_,
        orders1_.order_id as order1_4_3_,
        orders1_.order_id as order1_4_0_,
        orders1_.order_name as order2_4_0_,
        orders1_.customer_id as customer3_4_0_ 
    from
        hibernate.customer customer0_ 
    left outer join
        hibernate.order orders1_ 
            on customer0_.customer_id=orders1_.customer_id 
    where
        customer0_.customer_id=?

5.batch-size 屬性,設定批量檢索集合的數量。

(1)默認情況下

@Test
public void testSetLazy() {
    List<Category> categories = session.createQuery("from Category").list();

    for(Category category : categories) {
        System.out.println(category.getItems().size());
    }

}
Hibernate: 
    select
        category0_.category_id as category1_1_,
        category0_.category_name as category2_1_ 
    from
        hibernate.category category0_
Hibernate: 
    select
        items0_.category_id as category1_1_1_,
        items0_.item_id as item2_0_1_,
        item1_.item_id as item1_3_0_,
        item1_.item_name as item2_3_0_ 
    from
        hibernate.categories_items items0_ 
    inner join
        hibernate.item item1_ 
            on items0_.item_id=item1_.item_id 
    where
        items0_.category_id=?
2
Hibernate: 
    select
        items0_.category_id as category1_1_1_,
        items0_.item_id as item2_0_1_,
        item1_.item_id as item1_3_0_,
        item1_.item_name as item2_3_0_ 
    from
        hibernate.categories_items items0_ 
    inner join
        hibernate.item item1_ 
            on items0_.item_id=item1_.item_id 
    where
        items0_.category_id=?
2

(2)設置 batch-size="2"

@Test
public void testSetLazy() {
    List<Category> categories = session.createQuery("from Category").list();

    for(Category category : categories) {
        System.out.println(category.getItems().size());
    }

}
Hibernate: 
    select
        category0_.category_id as category1_1_,
        category0_.category_name as category2_1_ 
    from
        hibernate.category category0_
Hibernate: 
    select
        items0_.category_id as category1_1_1_,
        items0_.item_id as item2_0_1_,
        item1_.item_id as item1_3_0_,
        item1_.item_name as item2_3_0_ 
    from
        hibernate.categories_items items0_ 
    inner join
        hibernate.item item1_ 
            on items0_.item_id=item1_.item_id 
    where
        items0_.category_id in (
            ?, ?
        )
2
2

五、<many-to-one> 元素的 lazy 和 fetch 屬性

1.lazy 屬性

(1)proxy

采用延遲檢索策略。

(2)false

采用立即檢索策略。

2.fetch 屬性

(1)select(默認)

(2)join

表示使用迫切左外鏈接的方式,初始化 n 的一端關聯的 1 的一端的對象。

同樣,HQL 查詢會忽略 fetch 的取值為 join 的情況,此種情況下,若想批量初始化 1 的一端的代理對象,可以在 1 的一端的 class 節點添加 batch-size 屬性。

六、總結

介紹了 Hibernate 的檢索策略,包括累級別的檢索策略,和關聯級別的檢索策略。以及簡單介紹了 <many-to-one> 元素的 lazy 和 fetch 屬性。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved