Hibernate學習筆記四 查詢

HQL語法

一、基本語法java

String hql = " from  com.yyb.domain.Customer ";//完整寫法
String hql2 = " from  Customer "; //簡單寫法
String hql3 = " from java.lang.Object ";//查詢全部表

二、排序sql

//排序,和sql同樣
  String hql1 = " from  Customer order by cust_id asc ";

三、條件數據庫

String hql1 = " from  Customer where cust_id =? ";
String hql2 = " from  Customer where cust_id = :id ";

四、分頁數組

String hql1 = " from  Customer  ";//完整寫法
Query query = session.createQuery(hql1);
//limit ?,?
// (當前頁數-1)*每頁條數
query.setFirstResult(2);
query.setMaxResults(2);

五、聚合查詢session

String hql1 = " select count(*) from  Customer  ";
String hql2 = " select sum(cust_id) from  Customer  ";
String hql3 = " select avg(cust_id) from  Customer  ";
String hql4 = " select max(cust_id) from  Customer  ";
String hql5 = " select min(cust_id) from  Customer  ";

  Query query = session.createQuery(hql5);
  Number number = (Number) query.uniqueResult();dom

六、投影查詢jsp

    String hql1 = " select cust_name from  Customer  ";
    String hql2 = " select cust_name,cust_id from  Customer  ";
    String hql3 = " select new Customer(cust_id,cust_name) from Customer  ";//查詢出來封裝到對象中,必須有相應的構造函數和空參構造函數

七、多表查詢函數

//回顧-原生SQL
  // 交叉鏈接-笛卡爾積(避免)
//        select * from A,B 
    // 內鏈接
//        |-隱式內鏈接
//            select * from A,B  where b.aid = a.id
//        |-顯式內鏈接
//            select * from A inner join B on b.aid = a.id
    // 外鏈接
//        |- 左外
//            select * from A left [outer] join B on b.aid = a.id
//        |- 右外
//            select * from A right [outer] join B on b.aid = a.id
//---------------------------------------------------------------------
//HQL的多表查詢
        //內鏈接(迫切)
        //外鏈接
//            |-左外(迫切)
//            |-右外(迫切)

7.1內鏈接性能

//HQL 內鏈接 => 將鏈接的兩端對象分別返回.放到數組中.
    public void fun1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        String hql = " from Customer c inner join c.linkMens ";
        Query query = session.createQuery(hql);
        List<Object[]> list = query.list();
        for(Object[] arr : list){
            System.out.println(Arrays.toString(arr));
        }
        //----------------------------------------------------
        tx.commit();
        session.close();
        
    }

7.2迫切內鏈接,返回一個對象,另外一個對象也被封裝到了這個對象中。fetch

    @Test
    //HQL 迫切內鏈接 => 幫咱們進行封裝.返回值就是一個對象
    public void fun2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        String hql = " from Customer c inner join fetch c.linkMens ";
        
        Query query = session.createQuery(hql);
        
        List<Customer> list = query.list();
        
        System.out.println(list);
        //----------------------------------------------------
        tx.commit();
        session.close();
        
    }

7.3 左、右鏈接

String hql = " from Customer c left join c.linkMens ";
String hql = " from Customer c right join c.linkMens ";

 Criteria語法

 一、基本語法

Criteria c = session.createCriteria(Customer.class);
List<Customer> list = c.list();

二、條件

Criteria c = session.createCriteria(Customer.class);
// c.add(Restrictions.idEq(2l));
c.add(Restrictions.eq("cust_id",2l));
List<Customer> list = c.list();

三、分頁

Criteria c = session.createCriteria(Customer.class);
//limit ?,? 
c.setFirstResult(0);
c.setMaxResults(2);

四、排序

Criteria c = session.createCriteria(Customer.class);
c.addOrder(Order.asc("cust_id"));
//c.addOrder(Order.desc("cust_id"));      

五、統計

Criteria c = session.createCriteria(Customer.class);
//設置查詢目標
c.setProjection(Projections.rowCount());

離線查詢對象

離線查詢即不須要Session對象,能夠實現動態拼接查詢條件。

     DetachedCriteria dc  = DetachedCriteria.forClass(Customer.class);
        
        dc.add(Restrictions.idEq(6l));//拼裝條件(所有與普通Criteria一致)
        
        //----------------------------------------------------
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        Criteria c = dc.getExecutableCriteria(session);
        
        List list = c.list();
        
        System.out.println(list);
        //----------------------------------------------------
        tx.commit();
        session.close();

抓取策略

抓取策略是當應用程序須要在關聯關係間進行導航的時候,Hibernate如何獲取關聯對象的策略。

抓取策略是Hibernate提高性能的一種手段,能夠在獲取關聯對象的時候,對發送的語句進行優化,可是每每抓取策略須要和延遲加載一塊兒使用來提高性能。

延遲加載

延遲加載是Hibernate關聯關係對象默認的加載方式,延遲加載機制是爲了不一些無謂的性能開銷而提出來的,所謂延遲加載就是當在真正須要數據的時候,才真正執行數據加載操做。

延遲加載分爲兩類:類級別延遲 和關聯級別的延遲。

類級別延遲

類級別延遲是指查詢某個對象的時候,是否採用有延遲,這個一般在<class>標籤上配置lazy屬性。

get方法:沒有任何策略.調用即當即查詢數據庫加載數據.

load方法: 應用類級別的加載策略-懶加載|延遲加載。因此使用load方法去查詢的時候,不會立刻發送SQL語句,當真正使用該對象的時候,纔會發送SQL語句。

  • lazy:true(默認值), 查詢類時,會返回代理對象.會在使用屬性時,根據關聯的session查詢數據庫.加載數據.
  • lazy:false. load方法會與get方法沒有任何區別.調用時即加載數據.

示例:

//懶加載|延遲加載
public class Demo {
    
    @Test
    // get方法 : 當即加載.執行方法時當即發送sql語句查詢結果
    public void fun1(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        
        Customer c = session.get(Customer.class, 2l);
        
        System.out.println(c);
        //----------------------------------------------------
        tx.commit();
        session.close();
        
    }
    
    @Test
    // load方法(默認):是在執行時,不發送任何sql語句.返回一個對象.使用該對象時,才執行查詢.
    // 延遲加載: 僅僅得到沒有使用.不會查詢.在使用時才進行查詢.
    // 是否對類進行延遲加載: 能夠經過在class元素上配置lazy屬性來控制.
        //lazy:true  加載時,不查詢.使用時才查詢b
        //lazy:false 加載時當即查詢.
    public void fun2(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
        //----------------------------------------------------
        
        Customer c = session.load(Customer.class, 2l);
        
        //----------------------------------------------------
        tx.commit();
        session.close();
        System.out.println(c);
        
    }
<class name="Customer" table="cst_customer" lazy="false" >

類名中凡有$$的標識符都是代理對象。加強了Customer具備查詢數據庫的功能。

若是不想使用延遲加載,能夠把這個類的映射文件上的lazy設置爲false。也能夠將這個持久化類改成final修飾。此時沒法生成代理類,就會時延遲加載失效。

結論:爲了提升效率.建議使用延遲加載(懶加載)

注意:使用懶加載時要確保,調用屬性加載數據時,session仍是打開的.否則會拋出異常。

 關聯級別延遲

 關聯級別延遲是指查詢一個對象的關聯對象的時候是否採用延遲加載。這個一般在<set>或<many-to-one>上配置lazy屬性。

Customer c = session.get(Customer.class, 2l);
Set<LinkMan> linkMens = c.getLinkMens();//關聯級別

經過客戶查詢其關聯的聯繫人對象,在查詢聯繫人的時候是否採用延遲加載稱爲關聯級別的延遲。

<set>標籤上的lazy一般有三個取值:

  • true:默認值,採用延遲加載
  • false:檢索關聯對象的時候,不採用延遲加載
  • extra:及其惰性的

<many-to-one>標籤上的lazy一般有三個取值:

  • proxy:默認值,是否採用延遲加載取決於一的一方上的lazy屬性的值。
  • false:檢索關聯對象的時候,不採用延遲加載
  • no-proxy:不用研究

抓取策略

抓取策略值得是查詢某個對象的時候,如何抓取其關聯對象。這個也能夠經過配置完成。在關聯對象的標籤上配置fetch屬性。關聯上就分爲是在<set>和<many-to-one>上,也都有不一樣的取值。

<set>標籤上的fetch一般有三個取值:

  • select:默認值,發送的是普通的select語句查詢。
  • join:發送一條迫切左外連接去查詢
  • subselect:發送一條子查詢語句查詢其關聯對象。

<many-to-one>標籤上的fetch有兩個取值:

  • select:默認值,發送一條普通的select語句查詢關聯對象。
  • join:發送一條迫切左外連接語句去查詢其關聯對象。

fetch和lazy組合就會產生不少種的效果。其實不用擔憂,由於fetch若是設置爲join,lazy就會失效了。

演示:

<!-- 
        lazy屬性: 決定是否延遲加載
            true(默認值): 延遲加載,懶加載
            false: 當即加載
            extra: 極其懶惰
        fetch屬性: 決定加載策略.使用什麼類型的sql語句加載集合數據
            select(默認值): 單表查詢加載
            join: 使用多表查詢加載集合
            subselect:使用子查詢加載集合
     -->
     <!-- batch-size: 抓取集合的數量爲3.
             抓取客戶的集合時,一次抓取幾個客戶的聯繫人集合.
      -->
        <set name="linkMens" fecth="" lazy="'>
            <key column="lkm_cust_id" ></key>
           <one-to-many class="LinkMan" /> 
        </set>        

一、fetch:select,lazy:true的狀況

 1 //集合級別的關聯
 2     //fetch:select 單表查詢
 3     //lazy:true 使用時才加載集合數據.
 4     @Test
 5     public void fun1(){
 6         Session session = HibernateUtils.openSession();
 7         Transaction tx = session.beginTransaction();
 8         //----------------------------------------------------
 9         Customer c = session.get(Customer.class, 2l);
10         Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
11         System.out.println(linkMens);
12         //----------------------------------------------------
13         tx.commit();
14         session.close();
15         
16     }

在第9行查詢Customer的時候並無當即查詢linkMens,生成sql以下:

select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?

在第11行使用linkMens的時候纔去數據庫查,生成sql以下:

  select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?

二、fetch:select,lazy:false的狀況

 1 //集合級別的關聯
 2         //fetch:select 單表查詢
 3         //lazy:false 當即記載集合數據
 4         @Test
 5         public void fun2(){
 6             Session session = HibernateUtils.openSession();
 7             Transaction tx = session.beginTransaction();
 8             //----------------------------------------------------
 9             
10             Customer c = session.get(Customer.class, 2l);
11             
12             Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
13             
14             System.out.println(linkMens);
15             
16             //----------------------------------------------------
17             tx.commit();
18             session.close();
19             
20         }

在加載Customer的時候就會把關聯的表的數據查詢出來,生成sql以下:

    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?
Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?

三、fetch:select,lazy:extra的狀況

 1         //集合級別的關聯
 2         //fetch:select 單表查詢
 3         //lazy:extra 極其懶惰.與懶加載效果基本一致. 若是隻得到集合的size.
           //只查詢集合的size(count語句)
 4         @Test
 5         public void fun3(){
 6             Session session = HibernateUtils.openSession();
 7             Transaction tx = session.beginTransaction();
 8             //----------------------------------------------------
 9             
10             Customer c = session.get(Customer.class, 2l);
11             
12             Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
13             
14             System.out.println(linkMens.size());
15             
16             System.out.println(linkMens);
17             
18             //----------------------------------------------------
19             tx.commit();
20             session.close();
21             
22         }

在第10行查詢Customer的時候並無當即查詢linkMens,生成sql以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?

在第14行須要使用的時候才查詢,並且並無把linkMens的數據查詢出來。生成sql以下:

Hibernate: 
    select
        count(lkm_id) 
    from
        cst_linkman 
    where
        lkm_cust_id =?

四、fetch:join,lazy:true的狀況

 1 //集合級別的關聯
 2     //fetch:join    多表查詢
 3     //lazy:true|false|extra 失效.當即加載.
 4     @Test
 5     public void fun4(){
 6         Session session = HibernateUtils.openSession();
 7         Transaction tx = session.beginTransaction();
 8         //----------------------------------------------------
 9 
10         Customer c = session.get(Customer.class, 1l);
11 
12         Set<LinkMan> linkMens = c.getLinkMens();//關聯級別
13 
14         System.out.println(linkMens.size());
15 
16         System.out.println(linkMens);
17 
18         //----------------------------------------------------
19         tx.commit();
20         session.close();
21 
22     }

在第10行查詢Customer的時候linkMens也一併被查詢出來,後面的操做再也不生成sql了,生成sql以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_,
        linkmens1_.lkm_cust_id as lkm_cus10_1_1_,
        linkmens1_.lkm_id as lkm_id1_1_1_,
        linkmens1_.lkm_id as lkm_id1_1_2_,
        linkmens1_.lkm_gender as lkm_gend2_1_2_,
        linkmens1_.lkm_name as lkm_name3_1_2_,
        linkmens1_.lkm_phone as lkm_phon4_1_2_,
        linkmens1_.lkm_email as lkm_emai5_1_2_,
        linkmens1_.lkm_qq as lkm_qq6_1_2_,
        linkmens1_.lkm_mobile as lkm_mobi7_1_2_,
        linkmens1_.lkm_memo as lkm_memo8_1_2_,
        linkmens1_.lkm_position as lkm_posi9_1_2_,
        linkmens1_.lkm_cust_id as lkm_cus10_1_2_ 
    from
        cst_customer customer0_ 
    left outer join
        cst_linkman linkmens1_ 
            on customer0_.cust_id=linkmens1_.lkm_cust_id 
    where
        customer0_.cust_id=?

五、fetch:subselect,lazy:true的狀況

 1 @Test
 2     //fetch: subselect 子查詢
 3     //lazy: true 懶加載
 4     public void fun5(){
 5         Session session = HibernateUtils.openSession();
 6         Transaction tx = session.beginTransaction();
 7         //----------------------------------------------------
 8         String  hql = "from Customer";
 9         Query query = session.createQuery(hql);
10         List<Customer> list = query.list();
11         for(Customer c:list){
12             System.out.println(c);
13             System.out.println(c.getLinkMens().size());
14             System.out.println(c.getLinkMens());
15         }
16         //----------------------------------------------------
17         tx.commit();
18         session.close();
19     }

在第10行查詢Customer的時候並無當即查詢linkMens,生成sql以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_,
        customer0_.cust_name as cust_nam2_0_,
        customer0_.cust_source as cust_sou3_0_,
        customer0_.cust_industry as cust_ind4_0_,
        customer0_.cust_level as cust_lev5_0_,
        customer0_.cust_linkman as cust_lin6_0_,
        customer0_.cust_phone as cust_pho7_0_,
        customer0_.cust_mobile as cust_mob8_0_ 
    from
        cst_customer customer0_

當執行到第13行時,使用子查詢獲取linkMens的數據,生成sql以下:

Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?

六、fetch:subselect,lazy:false的狀況

 1  @Test
 2     //fetch: subselect 子查詢
 3     //lazy: false 當即加載
 4     public void fun6(){
 5         Session session = HibernateUtils.openSession();
 6         Transaction tx = session.beginTransaction();
 7         //----------------------------------------------------
 8         String  hql = "from Customer";
 9         Query query = session.createQuery(hql);
10         List<Customer> list = query.list();
11         for(Customer c:list){
12             System.out.println(c);
13             System.out.println(c.getLinkMens().size());
14             System.out.println(c.getLinkMens());
15         }
16         //----------------------------------------------------
17         tx.commit();
18         session.close();
19     }

執行第10行時,會查詢出全部數據,生成sql以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_,
        customer0_.cust_name as cust_nam2_0_,
        customer0_.cust_source as cust_sou3_0_,
        customer0_.cust_industry as cust_ind4_0_,
        customer0_.cust_level as cust_lev5_0_,
        customer0_.cust_linkman as cust_lin6_0_,
        customer0_.cust_phone as cust_pho7_0_,
        customer0_.cust_mobile as cust_mob8_0_ 
    from
        cst_customer customer0_
Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?

七、fetch:subselect,lazy:extra的狀況

 1 @Test
 2     //fetch: subselect 子查詢
 3     //lazy: extra 極其懶惰
 4     public void fun7(){
 5         Session session = HibernateUtils.openSession();
 6         Transaction tx = session.beginTransaction();
 7         //----------------------------------------------------
 8         String  hql = "from Customer";
 9         Query query = session.createQuery(hql);
10         List<Customer> list = query.list();
11         for(Customer c:list){
12             System.out.println(c);
13             System.out.println(c.getLinkMens().size());
14             System.out.println(c.getLinkMens());
15         }
16         //----------------------------------------------------
17         tx.commit();
18         session.close();
19 
20     }

執行第10行時,查詢Customer對象,linkMens未查詢,生成SQL語句以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_,
        customer0_.cust_name as cust_nam2_0_,
        customer0_.cust_source as cust_sou3_0_,
        customer0_.cust_industry as cust_ind4_0_,
        customer0_.cust_level as cust_lev5_0_,
        customer0_.cust_linkman as cust_lin6_0_,
        customer0_.cust_phone as cust_pho7_0_,
        customer0_.cust_mobile as cust_mob8_0_ 
    from
        cst_customer customer0_

執行到13行時,生成sql語句以下:

Hibernate: 
    select
        count(lkm_id) 
    from
        cst_linkman 
    where
        lkm_cust_id =?

執行到14行時,生成sql語句以下:

Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_gender as lkm_gend2_1_1_,
        linkmens0_.lkm_name as lkm_name3_1_1_,
        linkmens0_.lkm_phone as lkm_phon4_1_1_,
        linkmens0_.lkm_email as lkm_emai5_1_1_,
        linkmens0_.lkm_qq as lkm_qq6_1_1_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_1_,
        linkmens0_.lkm_memo as lkm_memo8_1_1_,
        linkmens0_.lkm_position as lkm_posi9_1_1_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id=?

執行第二次的時候,全部數據都加載好了,就不會再去數據庫中查了。

關聯屬性策略

上面的代碼發轉過來,獲取linkMan,而後加載Customer。

示例:

<!-- 
        fetch 決定加載的sql語句
            select: 使用單表查詢(默認值)
            join : 多表查詢
        lazy  決定加載時機
            false: 當即加載
            proxy: 由customer的類級別加載策略決定.(默認值)
         -->
        <many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="" lazy=""  >
        </many-to-one>

一、fetch:select,lazy:proxy的狀況

 1     @Test
 2     //fetch:select    單表查詢
 3     //lazy:proxy  
 4         //customer-true 懶加載
 5     public void fun1(){
 6         Session session = HibernateUtils.openSession();
 7         Transaction tx = session.beginTransaction();
 8         //----------------------------------------------------
 9         
10         LinkMan lm = session.get(LinkMan.class, 1l);
11         
12         Customer customer = lm.getCustomer();
13         
14         System.out.println(customer);
15         
16         //----------------------------------------------------
17         tx.commit();
18         session.close();
19         
20     }

執行到第10行時,獲取linkman,生成SQL以下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkman0_ 
    where
        linkman0_.lkm_id=?

因爲Customer類上未作配置,全部默認使用延遲加載。當執行到12行時,生成SQL以下:

Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?

二、fetch:select,lazy:proxy,Customer上配置lazy="false"的狀況

仍是以上代碼,可是在Customer的Class配置上加入lazy="false",再次執行。當執行到10行時,生成SQL以下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkman0_ 
    where
        linkman0_.lkm_id=?
Hibernate: 
    select
        customer0_.cust_id as cust_id1_0_0_,
        customer0_.cust_name as cust_nam2_0_0_,
        customer0_.cust_source as cust_sou3_0_0_,
        customer0_.cust_industry as cust_ind4_0_0_,
        customer0_.cust_level as cust_lev5_0_0_,
        customer0_.cust_linkman as cust_lin6_0_0_,
        customer0_.cust_phone as cust_pho7_0_0_,
        customer0_.cust_mobile as cust_mob8_0_0_ 
    from
        cst_customer customer0_ 
    where
        customer0_.cust_id=?

三、fetch:select,lazy:false的狀況,同上面2的狀況同樣。

四、fetch:join,lazy:proxy的狀況

 1  @Test
 2     //fetch:join    多表
 3     //lazy: 失效
 4     public void fun3(){
 5         Session session = HibernateUtils.openSession();
 6         Transaction tx = session.beginTransaction();
 7         //----------------------------------------------------
 8         LinkMan lm = session.get(LinkMan.class, 3l);
 9         Customer customer = lm.getCustomer();
10         System.out.println(customer);
11         //----------------------------------------------------
12         tx.commit();
13         session.close();
14 
15     }

當執行到第8行時,生成SQL語句以下:

Hibernate: 
    select
        linkman0_.lkm_id as lkm_id1_1_0_,
        linkman0_.lkm_gender as lkm_gend2_1_0_,
        linkman0_.lkm_name as lkm_name3_1_0_,
        linkman0_.lkm_phone as lkm_phon4_1_0_,
        linkman0_.lkm_email as lkm_emai5_1_0_,
        linkman0_.lkm_qq as lkm_qq6_1_0_,
        linkman0_.lkm_mobile as lkm_mobi7_1_0_,
        linkman0_.lkm_memo as lkm_memo8_1_0_,
        linkman0_.lkm_position as lkm_posi9_1_0_,
        linkman0_.lkm_cust_id as lkm_cus10_1_0_,
        customer1_.cust_id as cust_id1_0_1_,
        customer1_.cust_name as cust_nam2_0_1_,
        customer1_.cust_source as cust_sou3_0_1_,
        customer1_.cust_industry as cust_ind4_0_1_,
        customer1_.cust_level as cust_lev5_0_1_,
        customer1_.cust_linkman as cust_lin6_0_1_,
        customer1_.cust_phone as cust_pho7_0_1_,
        customer1_.cust_mobile as cust_mob8_0_1_ 
    from
        cst_linkman linkman0_ 
    left outer join
        cst_customer customer1_ 
            on linkman0_.lkm_cust_id=customer1_.cust_id 
    where
        linkman0_.lkm_id=?

結論:爲了提升效率,fetch的選擇上應選select,lazy選擇true。因此所有使用默認值。

no-session問題

延遲加載的問題是指當咱們調用完action中的某個方法,在jsp頁面要顯示咱們想要的信息的時候,發如今dao中打開的session已經關閉了。

解決方式:擴大session的做用範圍。能夠在過濾器中放行以前打開session,放行以後關閉session。

批量抓取

 在抓取的策略中有一種叫作批量抓取,就是同時查詢多個對象的關聯對象時,能夠採用批量抓取進行優化。固然這個就不是特別重要了。經過配置batch-size來完成。

示例:

 1  @Test
 2         public void fun10(){
 3             Session session = HibernateUtils.openSession();
 4             Transaction tx = session.beginTransaction();
 5             //----------------------------------------------------
 6 
 7             String hql = "from Customer ";
 8             Query query = session.createQuery(hql);
 9             List<Customer> list = query.list();
10 
11             for(Customer c:list){
12                 System.out.println(c.getLinkMens());
13             }
14 
15             //----------------------------------------------------
16             tx.commit();
17             session.close();
18         }

在沒有配置批量抓取以前,每次執行到第12行時,就會生成SQL語句去數據庫查,循環幾回,就要查詢幾回。

進行批量抓取配置以後,從新執行上面代碼:

 <!-- batch-size: 抓取集合的數量爲3.
             抓取客戶的集合時,一次抓取幾個客戶的聯繫人集合.
      -->
        <set name="linkMens" batch-size="3"  >
            <key column="lkm_cust_id" ></key>
            <one-to-many class="LinkMan" />
        </set>

生成SQL語句以下:

Hibernate: 
    select
        linkmens0_.lkm_cust_id as lkm_cus10_1_1_,
        linkmens0_.lkm_id as lkm_id1_1_1_,
        linkmens0_.lkm_id as lkm_id1_1_0_,
        linkmens0_.lkm_gender as lkm_gend2_1_0_,
        linkmens0_.lkm_name as lkm_name3_1_0_,
        linkmens0_.lkm_phone as lkm_phon4_1_0_,
        linkmens0_.lkm_email as lkm_emai5_1_0_,
        linkmens0_.lkm_qq as lkm_qq6_1_0_,
        linkmens0_.lkm_mobile as lkm_mobi7_1_0_,
        linkmens0_.lkm_memo as lkm_memo8_1_0_,
        linkmens0_.lkm_position as lkm_posi9_1_0_,
        linkmens0_.lkm_cust_id as lkm_cus10_1_0_ 
    from
        cst_linkman linkmens0_ 
    where
        linkmens0_.lkm_cust_id in (
            ?, ?, ?
        )

此時一次會拿3條數據,而不會每次都到數據庫中查了。

相關文章
相關標籤/搜索