1. 程式人生 > >day29HibernateDay04(HQL/SQL/QBC查詢lazy和fetch 懶載入)

day29HibernateDay04(HQL/SQL/QBC查詢lazy和fetch 懶載入)

回顧
1、一對多關聯關係對映
    JavaBean的編寫
    編寫對映的配置檔案
    使用級聯儲存、刪除、孤兒刪除,使用cascade="save-update,delete,delte-orphan"
    放棄外來鍵的維護的權力,使用inverse="true"

2、多對多關聯關係對映
    儲存,必須放棄外來鍵的維護的權力

框架的查詢方式
1、唯一標識OID的檢索方式
    session.get(物件.class,OID)
2、物件的導航的方式  new User().getRole().getRname()
    Customer.getLinkmans() 先獲取顧客通過顧客獲取聯絡人的id然後查詢聯絡人的表獲得聯絡人
3、HQL的檢索方式
    Hibernate Query Language Hibernate的查詢語言
4、QBC的檢索方式
    Query By Criteria   條件查詢
5、SQL檢索方式
    本地的SQL檢索

HQL查詢方式概述
1、HQL的介紹
    HQL(Hibernate Query Language)是面向物件的查詢語言,和SQL查詢語言有些相似
    在Hibernate提供的各種檢索方式中,HQL是使用最廣的檢索方式
2、HQL和SQL的關係
    SQL查詢語言是面向物件的。Hibernate負責解析HQL查詢語句,然後根據物件-關係對映檔案中的對映資訊,把HQL查詢語句翻譯成相應的SQL語句
    HQL查詢語句的主體是域模型中的類及類的屬性
    SQL查詢語句是與關係資料庫繫結在一起的,SQL查詢語句中的主體是資料庫表及表的欄位

HQL的查詢演示
1、HQL的查詢格式
    支援  方法鏈的程式設計,即直接呼叫list()方法
    程式碼:
        session.createQuery("from Customer").list();
2、使用別名的方式
    session.createQuery("from Customer c").list();
    session.createQuery("select c from Customer c").list();
3、排序查詢
    排序查詢和SQL語句中的排序的語法是一樣的
        升序
            session.createQuery("from Customer order by cust_id").list();
        降序
            session.createQuery("from Customer order by cust_id desc").list();

4、分頁查詢
    Hibernate框架提供了分頁的方法,可以呼叫方法來完成分頁 limit ?,?   (當前頁-1)*pageSize
        setFirstResult(a)   從哪條記錄開始,如果查詢是從第一條開始,值是0
        setMaxResults(b)    每頁查詢的記錄條數

    List<LinkMan> list = session.createQuery("from LinkMan").setFirstResult(0).setMaxResults().list();

5、帶條件的查詢
    setParameter("?號的位置,預設從0開始","引數的值"),不用考慮引數的具體型別
    按位置繫結引數的條件查詢(指定下標值,預設從0開始)
    按名稱繫結引數的條件查詢(HQL語句中的問號換成 :名稱的方式)
        Query query = session.createQuery("from Linkman where lkm_name like ? order by lkm_id desc");
        query.setFirstResult(0).setMaxResults(3);
        query.setParameter(0,"%run%");
        List<Linkman> list = query.list();
        for(Linkman linkman:list){
            syso(linkman);
        }

投影查詢
1、投影查詢就是想查詢某一欄位的值或者某幾個欄位的值
    如果查詢多個欄位
        List<Object[]> list = session.createQuery("select c.cust_name,c.cust_level from Customer c").list();
        for(Object[] objects:list){
            syso(Arrays.toString(objects));
        }       
    如果查詢兩個欄位,也可以把這兩個欄位封裝到物件中
        現在持久化類中提供對應欄位的構造方法
        使用
            List<Customer> list = session.createQuery("select new Customer(c.cust_name,c.cust_level) from Customer c").list();
            for(Customer customer:list) {
                System.out.println(customer);
            }

聚合函式查詢
1、獲取總的記錄數
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        List<Number> list= session.createQuery("select  count(l) from Linkman l").list();
        Long count = list.get(0).longValue();
        System.out.println("數量:"+count);
        tr.commit();
2、獲取某一列資料的和
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        List<Number> list= session.createQuery("select  sum(lkm_id) from Linkman l").list();
        Long count = list.get(0).longValue();
        System.out.println("數量:"+count);
        tr.commit();

QBC檢索
0、QBC: query by criteria 按條件進行查詢
1、簡單查詢 使用的Criteria介面
        Criteria criteria = session.createCriteria(Customer.class);
        List<Customer> list = criteria.list();
        for(Customer customer:list){
            System.out.println(customer);
        }
2、需要使用addOrder()方法來設定引數,引數使用org.hibernate.criterion.Order物件 
        Session session= HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //建立QBC介面
        Criteria criteria = session.createCriteria(Linkman.class);

        //呼叫排序的方法,addOrder()
        criteria.addOrder(Order.desc("lkm_id"));
        List<Linkman> list = criteria.list();
        for(Linkman linkman:list){
            System.out.println(linkman);
        }
        tr.commit();
3、分頁查詢
    QBC的分頁查詢也是使用兩個方法
        criteria.setFirstResult(0);
        criteria.setMaxResults(3);
4、條件查詢(Criterion是查詢條件的介面,Restrictions類是Hibernate框架提供的工具類,使用該類來設定查詢條件)
    新增查詢使用Criteria介面的add方法,用來傳入條件
    使用Restrictions的新增條件的方法來新增條件
        Restrictions.eq     相等
        Restrictions.st     大於號
        Restrictions.ge     大於等於
        Restrictions.lt     小於
        Restrictions.le     小於等於
        Restrictions.between 在之間
        Restrictions.like   模糊查詢
        Restrictions.in     範圍
        Restrictions.and    並且 
        Restrictions.or     或者

        Session session= HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //建立QBC介面
        Criteria criteria = session.createCriteria(Linkman.class);

        //select * from cst_linkman where lkm_gender = 'man' or lkm_id >2L;

        criteria.add(Restrictions.or(Restrictions.eq("lkm_gender","man"),Restrictions.gt("lkm_id",3L)));
        List<Linkman> list = criteria.list();
        for(Linkman linkman:list){
            System.out.println(linkman);
        }

        tr.commit();

5、聚合函式查詢(Projection是聚合函式的介面,而Projections是Hibernate提供的工具類)
    需要使用criteria.setProjection
    Demo3#run9

離線條件查詢
1、離線條件查詢使用的是DetachedCriteria介面進行查詢,離線條件查詢物件在建立的時候,不需要使用Session物件,只是在查詢的時候使用Session物件即可
    Demo3#run10

SQL查詢方式
    Demo4#run1,run2

多表查詢
1、多表的查詢用HQL語句進行查詢 HQL語句和SQL語句的語法比較相似
    內連線查詢
        顯示內連線
            select * from customers c inner join orders o on c.cid = o.cno;
        隱式內連線
            select * from customers c ,orders o where c.cid = o.cno
    外連線
        左外連線
            select * from customers c left outer join orders o on c.cid=o.cno
        右外連線
            select * from customer c right outer join orders o on c.cid=o.cno
2、HQL的多表查詢
    迫切和非迫切
        非迫切返回結果是Object[]
        Demo5#run1
        迫切連線返回的結果是物件,把客戶的資訊封裝到客戶的物件中,把訂單的資訊封裝到客戶的Set集合中
        Demo5#run2
3、內連線查詢
    內連線使用 inner join,預設返回的是Object陣列

    迫切內連線 inner join fetch 返回的是實體物件

4、左外連線查詢
    左外連線:封裝成List<Object[]>

    迫切左外連線
    Session session =  HibernateUtils.getCurrentSession();
    Transaction tr = session.beginTransaction();
    List<Customer> list = session.createQuery("from Customer c left join fetch c.linkmans").list();
    Set<Customer> set = new HashSet<Customer>(list);
    for(Customer customer:list){
        syso(customer);
    }
    tr.commit();

延遲載入
屬性沒有好壞之分 只有適不適合
1、延遲載入先獲取到代理物件,當真正使用到該物件中的屬性的時候,才會傳送SQL語句,Hibernate框架提升效能的方式
2、類級別的延遲載入
    Session物件的load方法預設就是延遲載入
    Customer c = session.load(Customer.class,1L);沒有傳送SQL語句,當使用該物件的屬性時,才傳送SQL語句
    標籤的優先順序高
    使類級別的延遲載入失效
        在<class>標籤上配置 lazy="false" xxx.hbm.xml
        Hibernate initialize(Object proxy)
        Demo6#run2
3、關聯級別的延遲載入(查詢某個客戶,當檢視該客戶下的所有聯絡人是否是延遲載入)    
    預設是延遲載入     
        Demo6#run3

查詢策略
1、使用Hibernate查詢一個物件的時候,查詢其關聯物件,應該如何查詢,是Hibernate的一種優化手段
2、Hibernate框架的檢索策略解決的問題
    查詢的時機
        Customer c1 = session.get(Customer.class,1L);
        syso(c1.getLinkmans().size());

        lazy屬性解決查詢的時機的問題,需要配置是否採用延遲載入
    查詢的語句形式
        List<Customer> list = session.createQuery("from Customer").list();
        for(Customer c:list){
            syso(c.getLinkmans())
        }       
        fetch屬性可以解決查詢語句的形式的問題

set標籤上配置策略
1、使用fetch和lazy
    fetch的取值        控制SQL語句生成的格式
        select      預設值,傳送查詢語句
        join        連線查詢,傳送的是一條迫切左外連線,配置了join.lazy就失效了
        subselect   子查詢,傳送一條子查詢查詢其關聯物件(需要使用list()方法進行測試)
    lazy的取值     查詢關聯物件的時候是否採用延遲
        true        預設 延遲
        false       不延遲
        extra       極其延遲
2、set標籤上的預設值是fetch="select" lazy="true"
3、hibernate框架都採用了預設值,開發中基本都是預設值

many-to-one 標籤上配置策略
1、<many-to-one>標籤上使用fetch和lazy屬性
    fetch的取值        控制sql的格式
        select      預設,傳送基本select語句查詢
        join        傳送迫切左外連線查詢 lazy任何值一樣的效果

    lazy的查詢         控制載入關聯物件是否採用延遲
        false       不採用延遲載入
        proxy       預設值,代理,現在是否採用延遲
            由另一端上的<class>的lazy確定,如果這端的class上的lazy="true" proxy的值就是true(延遲載入)
            如果class上lazy="false" proxy的值就是false

屬性沒有好壞之分 只有適不適合