Hibernate學習筆記--------4.查詢

来源:http://www.cnblogs.com/lzq1065763582/archive/2016/07/31/5723250.html
-Advertisement-
Play Games

一、Get/Load Get方法是立即檢索,而load是延遲檢索,他們都是根據主鍵進行查詢。在<class>標簽中,若把lazy屬性改為false,load方法就會立即檢索,class中的lazy屬性僅對load方法有效。在使用load時,當資料庫沒有找到數據時,會有ObjectNotFoundEx ...


一、Get/Load

Get方法是立即檢索,而load是延遲檢索,他們都是根據主鍵進行查詢。在<class>標簽中,若把lazy屬性改為false,load方法就會立即檢索,class中的lazy屬性僅對load方法有效。在使用load時,當資料庫沒有找到數據時,會有ObjectNotFoundException,異常。

 

1   public void LazyTest() {
2         //lazy 改為false或者true,查看列印sql的時機
3         Tb_User u = session.load(Tb_User.class, "1");
4         //System.out.println(u.getName()); 
5     }

 

二、1-n或多對多的查詢

2.1 set 標簽的lazy屬性 可以設置為三種值:true,false,extra。

  1. 預設為懶載入策略,即lazy預設為true
  2. Lazy為false時,會採用立即載入
  3. Extra會儘可能的延遲集合初始化的時機,可以重列印的sql語句發現,使用了count
  select
        count(ID) 
    from
        TB_ORDER 
    where
        userid =?

 

2.2   set標簽的batch-size屬性,確定批量初始化集合元素的個數

2.3   set標簽的fetch屬性,預設值為select,確定初始化集合的方式

  1.select ,通過正常的方式來初始化set

  2.subselect,通過子查詢的方式來初始化所有的set集合,lazty屬性有效,batch-size屬性失效,此時sql語句

Hibernate: 
    select
        orders0_.userid as userid6_0_1_,
        orders0_.ID as ID1_0_1_,
        orders0_.ID as ID1_0_0_,
        orders0_.NAME as NAME2_0_0_,
        orders0_.MONEY as MONEY3_0_0_,
        orders0_.COUNT as COUNT4_0_0_,
        orders0_.CREATETIME as CREATETIME5_0_0_,
        orders0_.userid as userid6_0_0_ 
    from
        TB_ORDER orders0_ 
    where
        orders0_.userid in (
            select
                tb_user0_.ID 
            from
                TB_USER tb_user0_
        )

  2.4  join,lazy會失效,採用左外連接查詢。若使用hql查詢,會忽略fetch=join屬性

三、n-1的查詢

1. many-to-one 的 lazy屬性有三個取值:proxy 延遲檢索,no-proxy,false 立即檢索

2.many-to-one 的 fetch屬性有兩個取值:select,join,作用和上面的一樣。

3.batch-size屬性是加到1方的class標簽上的,這裡不是加到many-to-one上的!

四、採用hql查詢

1.使用步驟:

-用過Session的createQuery方法創建一個Query對象,參數為HQL語句

-動態的綁定參數(按參數名字綁定 :參數名,按參數位置綁定 ?)

 1     //基於參數位置綁定參數值
 2     @Test
 3     public void test1(){
 4         Query query = session.createQuery("FROM Tb_User WHERE name = ? AND id = ?");
 5         query.setParameter(0, "1");
 6         query.setParameter(1, "1");
 7         List<Tb_User> list = query.getResultList();
 8         System.out.println(list.size());
 9     }
10     
11     //基於參數名稱綁定參數值
12     @Test
13     public void test2(){
14         Query query = session.createQuery("FROM Tb_User WHERE name = :name AND id = :id");
15         query.setParameter("name", "1");
16         query.setParameter("id", "1");
17         List<Tb_User> list = query.getResultList();
18         System.out.println(list.size());
19     }

 

-調用query相關方法執行查詢語句

2.分頁查詢  兩個相關方法 setFirsetResult | setMaxResult

 1     //分頁測試
 2     @Test
 3     public void pageTest(){
 4         Query query = session.createQuery("SELECT id FROM Tb_User");
 5         int pageNo = 2;//當前頁數
 6         int pageSize = 4;//每頁大小
 7         
 8         List<String> list = query
 9                 .setFirstResult((pageNo - 1) * pageSize)
10                 .setMaxResults(4).getResultList();
11         for(String u : list){
12             System.out.println(u);
13         }
14     }

3.命名查詢 getNamedQuery

命名查詢可以讓我們在xml中定義hql語句,在映射文件中,class標簽外添加;這裡用CDATA是因為若hql中有大於>或小於<等符號時,可以避免衝突

<query name = "findUserByName">
    <![CDATA[FROM Tb_User a WHERE a.name = :name]]>
</query>

然後通過name屬性來執行該語句

  @Test
    public void nameQuery(){
        Query query = session.getNamedQuery("findUserByName");
        List<Tb_User> list = query.setParameter("name", "1").getResultList();
        System.out.println(list.size());
    }

4.投影查詢 查詢表中某些欄位

這裡選擇了兩個欄位,因此每條數據查詢出來是一個object數組,由於有多條數據,所以就用了List<Object[]>來保存結果,若只查詢一個欄位,則可用List<T>來保存結果

    @Test
    public void filedQuery(){
        String hql = "SELECT a.id ,a.name FROM Tb_User a";
        Query query = session.createQuery(hql);
        List<Object[]> result = query.getResultList();
        
        for(Object[] objs: result){
            System.out.println(Arrays.asList(objs));
            //System.out.println(objs[0]);
        }
    }

當然,也可以在查詢出來的同時初始化這個類,如下,註意需要在Tb_User中添加一個只有id和name的構造函數。

    @Test
    public void filedQuery2(){
        String hql = "SELECT new Tb_User( a.id ,a.name ) FROM Tb_User a";
        Query query = session.createQuery(hql);
        List<Tb_User> result = query.getResultList();
        
        for(Tb_User u: result){
            System.out.println(u);
        }
    }

5.報表查詢,hql可用GROUP BY 和 HAVING 關鍵字,可以調用一下的聚集函數

-count()

-min()

-max()

-sum()

-avg()

//查詢每個用戶的最大金額和最小金額
    @Test
    public void GroupQuery(){
        String hql = "SELECT min(a.money) ,max(a.money) FROM Tb_Order a "+
                     "GROUP BY a.user";
        Query query = session.createQuery(hql);
        List<Object[]> result = query.getResultList();
        
        for(Object[] objs: result){
            System.out.println(Arrays.asList(objs));
            //System.out.println(objs[0]);
        }
    }

6.左外連接

左外連接有兩種關鍵字:LEFT JOIN 和 LEFT JOIN FETCH

LEFT JOIN FETCH的方式是查出來,並且立即初始化集合,集合可能包含有重覆的元素,需要去重。去重可用hql的distinct或者hashset集合

    @Test
    public void leftJoinFetch() {
        String hql = "From Tb_User a LEFT JOIN FETCH a.orders";
        
        //String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN FETCH a.orders"; //hql去掉重覆的欄位
        Query query = session.createQuery(hql);
        List<Tb_User> list = query.getResultList();
        //list = new ArrayList<Tb_User>(new LinkedHashSet<Tb_User>(list));//hashset去掉重覆欄位
        for(Tb_User u : list){
            System.out.println(u.getName() +"-"+ u.getOrders().size());
        }
    }

 

LEFT JOIN方式,預設查出來每條數據是一個對象數組,每個對象數組包含了Tb_User和Tb_Order,但是他並沒有初始話集合,初始化集合的操作需要更加映射文件的配置來。可能會有重覆,但是只能用hql的distinct關鍵字去重 

    @Test
    public void leftJoin() {
        String hql = "From Tb_User a LEFT JOIN a.orders";

        Query query = session.createQuery(hql);
        List<Object[]> list = query.getResultList();
        
        for(Object[] objs : list){
            System.out.println(Arrays.asList(objs));
        }
    }

這下麵這種情況下,他會根據user映射文件的配置查詢資料庫得到他order的數量

    @Test
    public void leftJoin2() {
        String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN a.orders";

        Query query = session.createQuery(hql);
        List<Tb_User> list = query.getResultList();
        
        for(Tb_User u : list){
            System.out.println(u.getName() +"-"+ u.getOrders().size());
        }
    }

內鏈接也有兩個INNER JOIN FETCH 和INNER JOIN 和左外連接的區別在於他不會查詢左表不符合條件的記錄,在這裡即是不返回訂單為0的用戶。

五、QBC(Query By Criteria) 面向對象的查詢

使用Criteria的介面來實現

    @Test
    public void qbcTest(){
        //1.創建一個Criteria對象
        Criteria criteria = session.createCriteria(Tb_User.class);
        //2.添加查詢條件
        criteria.add(Restrictions.eq("id","1"));
        //3.執行查詢
        Tb_User u = (Tb_User)criteria.uniqueResult();
        System.out.println(u);
    }

他們的and或者or的查詢方式

    @Test
    public void qbcTest2(){
        Criteria criteria = session.createCriteria(Tb_User.class);
        // AND : 使用Conjunction表示
        Conjunction conjunction = Restrictions.conjunction();
        conjunction.add(Restrictions.like("name","1",MatchMode.ANYWHERE));
        conjunction.add(Restrictions.eq("id", "1"));
        criteria.add(conjunction);
        System.out.println(criteria.list());
        //or
        Criteria criteria1 = session.createCriteria(Tb_Order.class);
        Disjunction disjunction = Restrictions.disjunction();
        disjunction.add(Restrictions.ge("money",2.0));
        disjunction.add(Restrictions.eq("name", "aa"));
        criteria1.add(disjunction);
        System.out.println(criteria1.list().size());
    }

criteria的統計查詢

    @Test
    public void qbcTest3(){
        
        Criteria criteria = session.createCriteria(Tb_Order.class);
        //統計查詢:使用prijection來表示
        criteria.setProjection(Projections.max("money"));
        //添加排序
        //criteria.addOrder(Order.asc("id"));
        System.out.println(criteria.uniqueResult());
    }

他的分頁和query.getResultList方法是一樣的

六、本地sql查詢

若自己寫sql查詢出來是一個對象數組,使用起來感覺怪怪的。

    @Test
    public void nativeSql(){
        String sql = "select * from Tb_User where name = :name";
        Query query = session.createSQLQuery(sql);
        query.setParameter("name", "1");
        List<Object[]> list = query.getResultList();
        for(Object[] u : list){
            System.out.println(Arrays.asList(u));
        }
    }

若要執行其他sql

    @Test
    public void nativeSql(){
        UUID u = UUID.randomUUID();
        String sql = "insert into Tb_User(id,name) values (:id,:name)";
        Query query = session.createSQLQuery(sql);
        query.setParameter("id", u.toString());
        query.setParameter("name", u.toString());
        query.executeUpdate();
    }

Demo地址:http://pan.baidu.com/s/1kUT9H91


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 系列 《使用sklearn進行集成學習——理論》 《使用sklearn進行集成學習——實踐》 目錄 1 Random Forest和Gradient Tree Boosting參數詳解2 如何調參? 2.1 調參的目標:偏差和方差的協調 2.2 參數對整體模型性能的影響 2.3 一個朴實的方案:貪心 ...
  • Introduction: 新語言, 新思維 Formatting Indentation: 預設tab Line Length: 無限制, 會自動換行 Parentheses: 圓括弧, 無限制, 但會自動去掉if, switch, for控制結構中的圓括弧. 使用gofmt命令自動格式源碼. C... ...
  • 前言:今天來回顧下SpringMVC的開發原理, 使用圖文並茂的方式 來解析其中的內幕, 我相信懂了其中的運行機制後, 對於面試中SpringMVC大家都可以說so easy了. 一, 圖示法 第二張圖的前端控制器應為DispatcherServlet. 看完圖中的整體流程後, 我們再使用實際代碼來 ...
  • 前言:說起單例模式,可能大家都熟悉,可以說是設計模式中出現頻率最高的一個,為了徹底弄清單例,在這裡我將說明何為單例,單例模式的演變,已經和靜態類之間的區別等。 1:概念 何為單例,就是在一個應用程式中只能有一個實例,就是保證對象只能被new一次。 2:懶漢模式 懶漢我覺得這個名字很形象,就是很懶,所 ...
  • 對象的生成 創建一個對象包括對象的聲明、實例化、初始化三部分。 1.聲明 類名對象名 聲明並不是為對象分配記憶體空間,而只是分配一個引用空間。對象的引用類似於指針,是32位的地址空間,它的值指向一個中間的數據結構,它儲存有關數據類型的信息以及當前對象所在的堆的地址,而對於對象所在的實際的記憶體地址是不可 ...
  • 題意是將一串數字轉換成另一種形式。比如5553141轉換成2個1,1個3,1個4,3個5,即21131435。1000000000000轉換成12011。數字的個數是可能超過9個的。n個m,m是從小到大排序。 輸出的結果又四種情況,建議判斷的時候就按照題目的順序進行判斷,否則可能出錯。第一種情況是進 ...
  • 題目鏈接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860 My思路: 先用兩個字元串儲存這兩個實數,然後再用另外兩個字元串儲存去掉符號和前後多餘的0後的新"實數",最後只需要比較兩個化簡後的新字元就ok了。 My代碼實現: 1 #includ ...
  • 用php進行靜態類型編程,估計是我的一個心結。 依次有幾篇文章都記錄了我的一些探索: 通過指定函數/方法形參類型提高PHP代碼可靠性 http://www.cnblogs.com/x3d/p/4285787.html 用Yii框架中的collections體驗PHP類型化編程 http://www. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...