Hibernate查詢方式

藍星花發表於2017-12-06
Hibernate查詢方式

OID查詢
     它就是根據id查詢一個實體
     涉及的方法:
          get(Class clazz,Serializable id):引數1是要查詢的實體位元組碼,引數2:是要查詢的id。
          load(Class clazz,Serializable id):引數1是要查詢的實體位元組碼,引數2:是要查詢的id。
Hibernate的檢索策略
     類級別檢索策略:
          get方法:
               它永遠都是立即載入。返回的物件是實體類型別。
               立即載入的含義:不管用不用,都馬上發起查詢。
          load方法:
               它預設是延遲載入。返回的是實體類物件的代理物件。
               它可以通過配置的方式改為立即載入。配置的位置是對映檔案的class標籤。
               涉及的屬性是:lazy。含義就是是否延遲載入。 取值true延遲載入(預設值) false不是延遲載入
               延遲載入的含義:什麼時候用,什麼時候真正發起查詢。

測試OID檢索方式

[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import org.hibernate.Session;  
  4. import org.hibernate.Transaction;  
  5. import org.junit.Test;  
  6.   
  7. import com.pc.hibernate.domain.Customer;  
  8. import com.pc.hibernate.utils.HibernateUtils;  
  9.   
  10. /** 
  11.  * Hibernate中的查詢方式: 
  12.  *         OID查詢: 
  13.  *             它就是根據id查詢一個實體 
  14.  *         涉及的方法: 
  15.  *             get(Class clazz,Serializable id):引數1是要查詢的實體位元組碼,引數2:是要查詢的id。 
  16.  *            load(Class clazz,Serializable id):引數1是要查詢的實體位元組碼,引數2:是要查詢的id。 
  17.  * 
  18.  * Hibernate的檢索策略 
  19.  *       類級別檢索策略: 
  20.  *          get方法: 
  21.  *             它永遠都是立即載入。返回的物件是實體類型別。 
  22.  *             立即載入的含義:不管用不用,都馬上發起查詢。 
  23.  *         load方法: 
  24.  *             它預設是延遲載入。返回的是實體類物件的代理物件。 
  25.  *             它可以通過配置的方式改為立即載入。配置的位置是對映檔案的class標籤。 
  26.  *             涉及的屬性是:lazy。含義就是是否延遲載入。 取值true延遲載入(預設值) false不是延遲載入 
  27.  *             延遲載入的含義:什麼時候用,什麼時候真正發起查詢。 
  28.  * @author Switch 
  29.  * 
  30.  */  
  31. public class TestOIDQuery {  
  32.     /** 
  33.      * 需求: 
  34.      *     查詢id為1的客戶 
  35.      */  
  36.     @Test  
  37.     public void test1() {  
  38.         Session session = HibernateUtils.getCurrentSession();  
  39.         Transaction transaction = session.beginTransaction();  
  40.         Customer customer = session.get(Customer.class, 1L);  
  41.         transaction.commit();  
  42.         // 輸出1和客戶資訊  
  43.         System.out.println(customer.getCustId());  
  44.         System.out.println(customer);  
  45.     }  
  46.   
  47.     /** 
  48.      * 需求: 
  49.      *     查詢id為1的客戶 
  50.      */  
  51.     @Test  
  52.     public void test2() {  
  53.         Session session = HibernateUtils.getCurrentSession();  
  54.         Transaction transaction = session.beginTransaction();  
  55.         Customer customer = session.load(Customer.class, 1L);  
  56.         transaction.commit();  
  57.         // 輸出1和報錯could not initialize proxy - no Session  
  58.         // 當<class name="Customer" table="cst_customer" lazy="false">時  
  59.         // 該方法正確,因為這時候已經不延遲載入了  
  60.         System.out.println(customer.getCustId());  
  61.         System.out.println(customer);  
  62.     }  
  63. }  


物件導航查詢
     物件圖導航檢索方式是根據己經載入的物件,導航到他的關聯物件 。它利用類與類之間的關係來檢索物件 。譬如要查詢一個聯絡人對應的客戶,就可以由聯絡人物件自動導航找到聯絡人所屬的客戶物件。當然,前提是必須在物件關係對映檔案上配置了多對一的關係。

     當我們兩個實體類有關聯關係時(一對多,多對一等等),在獲取一個實體時,可以根據物件的方法,獲取該實體關聯物件的資料。
     customer.getLinkMans();獲取當前客戶下的所有聯絡人
     linkman.getCustomer();獲取當前聯絡人所屬客戶。

[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import java.util.List;  
  4. import java.util.Set;  
  5.   
  6. import org.hibernate.SQLQuery;  
  7. import org.hibernate.Session;  
  8. import org.hibernate.Transaction;  
  9. import org.junit.Test;  
  10.   
  11. import com.pc.hibernate.domain.Customer;  
  12. import com.pc.hibernate.domain.LinkMan;  
  13. import com.pc.hibernate.utils.HibernateUtils;  
  14.   
  15. /** 
  16.  * 
  17.  * Hibernate中的查詢方式: 
  18.  *         物件導航查詢 
  19.  *             當我們兩個實體類有關聯關係時(一對多,多對一等等),在獲取一個實體時,可以根據物件的方法,獲取該實體關聯物件的資料。 
  20.  *             customer.getLinkMans();獲取當前客戶下的所有聯絡人 
  21.  *             linkman.getCustomer();獲取當前聯絡人所屬客戶。 
  22.  * 
  23.  * @author Switch 
  24.  */  
  25. public class TestObjectNavigationQuery {  
  26.     /** 
  27.      * 一般情況下我們都會有一個這樣的方法:根據id查詢一個實體。 
  28.      * 任何實體都應該有這麼個方法 
  29.      */  
  30.     public Customer findById(Long custId){  
  31.         Session s = HibernateUtils.getCurrentSession();  
  32.         Transaction tx = s.beginTransaction();  
  33.         Customer c1 = s.get(Customer.class, custId);  
  34.         tx.commit();  
  35.         return c1;  
  36.     }  
  37.   
  38.     /** 
  39.      * 根據客戶id查詢聯絡人資訊 
  40.      * @param custId 
  41.      * @return 
  42.      */  
  43.     public List<LinkMan> findLinkManByCid(Long custId){  
  44.         Session s = HibernateUtils.getCurrentSession();  
  45.         Transaction tx = s.beginTransaction();  
  46.         SQLQuery query = s.createSQLQuery("select * from cst_linkman where lkm_cust_id = ? ");  
  47.         query.setLong(0, custId);  
  48.         query.addEntity(LinkMan.class);  
  49.         @SuppressWarnings("unchecked")  
  50.         List<LinkMan> mans = query.list();  
  51.         tx.commit();  
  52.         return mans;  
  53.     }  
  54.   
  55.     /** 
  56.      * 需求: 
  57.      *     查詢id為1的客戶下的所有聯絡人 
  58.      */  
  59.     @Test  
  60.     public void test1(){  
  61.         // 傳統的使用方式  
  62.         List<LinkMan> list = findLinkManByCid(1L);  
  63.         System.out.println(list);  
  64.   
  65.         Customer c = findById(1L);  
  66.         //物件導航查詢  
  67.         // 需要將Customer上對應於LinkMan的關係檢索策略的懶載入關閉  
  68.         Set<LinkMan> linkmans = c.getLinkMans();  
  69.         for(LinkMan linkMan : linkmans){  
  70.             System.out.println(linkMan);  
  71.         }  
  72.     }  
  73.   
  74.   
  75.     /** 
  76.      * 需求: 
  77.      *     查詢id為5的聯絡人所屬客戶 
  78.      */  
  79.     @Test  
  80.     public void test2() {  
  81.         Session session = HibernateUtils.openSession();  
  82.         Transaction transaction = session.beginTransaction();  
  83.         LinkMan linkMan = session.get(LinkMan.class, 5L);  
  84.         // 物件導航查詢  
  85.         System.out.println(linkMan.getCustomer());  
  86.         transaction.commit();  
  87.   
  88.     }  
  89.   
  90. }  


HQL查詢
     HQL (Hibernate Query Language ) 是物件導向的查詢語言,它和 SQL 查詢語言有些相似 ,但它使用的是類、物件和屬性的概念 ,而沒有表和欄位的概念 。在Hibernate提供的各種檢索方式中 ,HQL是官方推薦的查詢語言,也是使用最廣泛的一種檢索 方式。
     涉及的物件:
          Query
     如何獲取Query:
          session.createQuery(String hql);
     HQL語句寫法:
          表名用實體類名稱替代
          欄位名用實體類屬性名稱(get/set方法後面的部分,並且把首字母轉小寫)

     Hibernate 進行 多表查詢與 SQL 其實是很相似的 ,但是 HQL 會在原來 SQL 分類的基礎上又多出來一些操作 。

HQL  的多表連線查詢的分類如下 :
  • 交叉連線
  • 內連線
    • 顯式內連線
    • 隱式內連線
    • 迫切內連線
  • 外連線
    • 左外連線
    • 迫切左外連線

     其實這些連線查詢語法大致都是一致的,就是HQL查詢的是物件而SQL查詢的是表。那麼我們來比較一下SQL和HQL的連線查詢。

SQL  連線查詢
  1. SELECT  * FROM  cst_customer c INNER JOIN cst_linkman 1 ON c.cust_id = l.lkm_cust_id;  

HQL 連線的查詢


  1. from Customer c inner join c.linkMans  

     在HQL中,我們不用寫關聯宇段了,因為客戶中的聯絡人的集合其實對應的就是外來鍵,所以我們在inner join的後面直接可以寫 c.linkMans。
     迫切內連線其實就是在內連線的inner join後新增一個fetch關鍵字。

  1. from Customer c inner join fetch c.linkMans  

     內連線或是迫切內連線傳送的底層SQL都是一樣的,而且在生成的SQL語句中也沒有fetch關鍵字,當然fetch本身就不是SQL語句的關鍵字。所以一定要注意,fetch只能在HQL中使用的,生成了SQL語句以後,fetch就消失了 。
     其實HQL內連線查詢的和SQL的內連線查詢到的結果集是一樣的 ,都是兩個表的交集部分的資料。
     然後在封裝資料的時候,普通內連線會將屬於客戶的資料封裝到Customer物件中,會將屬於聯絡人的資料封裝到LinkMan物件中,所以每條記錄都會是裝有兩個物件的集合,所以封裝以後的資料是 List<Object[ ]>,在Object[ ]中有兩個物件一個是 Customer另一個是 LinkMan 。
     那麼加了fetch以後,雖然查詢到的資料是一樣的,但是Hibernate發現HQL中有fetch就會將資料封裝到一個物件中,把屬於客戶的資料封裝到Customer物件中,將屬於聯絡人的部分封裝到Customer中的聯絡人的集合中,這樣最後封裝完成以後是一個 List<Customer> 中。

測試HQL方式
[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.hibernate.Query;  
  6. import org.hibernate.Session;  
  7. import org.hibernate.Transaction;  
  8. import org.junit.Test;  
  9.   
  10. import com.pc.hibernate.domain.Customer;  
  11. import com.pc.hibernate.domain.LinkMan;  
  12. import com.pc.hibernate.utils.HibernateUtils;  
  13.   
  14. /** 
  15.  * Hibernate中的查詢方式: 
  16.  *         HQL查詢: 
  17.  *             它是使用HQL語句進行查詢的。 HQL:Hiberante Query Language 
  18.  *         涉及的物件: 
  19.  *             Query 
  20.  *         如何獲取Query: 
  21.  *             session.createQuery(String hql); 
  22.  *         HQL語句寫法: 
  23.  *             表名用實體類名稱替代 
  24.  *             欄位名用實體類屬性名稱(get/set方法後面的部分,並且把首字母轉小寫) 
  25.  * 
  26.  * @author Switch 
  27.  */  
  28. public class TestHQLQuery {  
  29.     /** 
  30.      * 查詢所有 
  31.      * 需求:查詢所有客戶 
  32.      */  
  33.     @Test  
  34.     public void test1() {  
  35.         Session session = HibernateUtils.openSession();  
  36.         Transaction transaction = session.beginTransaction();  
  37.         // 查詢所有客戶  
  38.         Query query = session.createQuery("from Customer");  
  39.         @SuppressWarnings("unchecked")  
  40.         List<Customer> customers = query.list();  
  41.         transaction.commit();  
  42.         for (Customer customer : customers) {  
  43.             System.out.println(customer);  
  44.         }  
  45.     }  
  46.   
  47.     /** 
  48.      * 條件查詢: 
  49.      *     需求: 
  50.      *         查詢客戶級別是23的,客戶名稱帶有 集 字的 
  51.      *  給HQL語句加條件用where 
  52.      *  HQL語句的引數佔位符也可以使用? 
  53.      *  hibernate中,引數佔位符是從0開始的。 
  54.      */  
  55.     @Test  
  56.     public void test2(){  
  57.         Session session = HibernateUtils.openSession();  
  58.         Transaction transaction = session.beginTransaction();  
  59.         // 查詢客戶級別是23的,客戶名稱帶有 集 字的  
  60.         Query query = session.createQuery("from Customer where custLevel = ? and custName like ?");  
  61.         query.setString(0"23");  
  62.         query.setString(1"%集%");  
  63.         @SuppressWarnings("unchecked")  
  64.         List<Customer> customers = query.list();  
  65.         transaction.commit();  
  66.         for (Customer customer : customers) {  
  67.             System.out.println(customer);  
  68.         }  
  69.     }  
  70.   
  71.     /** 
  72.      * 具名查詢: 
  73.      *     給引數佔位符提供一個具體的名稱 
  74.      * HQL語句中的寫法: 
  75.      *         需要使用    :引數名稱 
  76.      *         例如:        :custLevel    :custName 
  77.      * 引數站位符賦值的寫法: 
  78.      *         需要注意:此處不能寫冒號,直接寫冒號後面的部分 
  79.      */  
  80.     @Test  
  81.     public void test3(){  
  82.         Session session = HibernateUtils.openSession();  
  83.         Transaction transaction = session.beginTransaction();  
  84.         // 查詢客戶級別是23的,客戶名稱帶有 集 字的  
  85.         // 給引數佔位符提供一個具體的名稱  
  86.         Query query = session.createQuery("from Customer where custLevel = :custLevel and custName like :custName");  
  87.         query.setString("custLevel""23");  
  88.         query.setString("custName""%集%");  
  89.         @SuppressWarnings("unchecked")  
  90.         List<Customer> customers = query.list();  
  91.         transaction.commit();  
  92.         for (Customer customer : customers) {  
  93.             System.out.println(customer);  
  94.         }  
  95.     }  
  96.   
  97.   
  98.     /** 
  99.      * 排序查詢: 
  100.      *      使用HQL語句,給查詢結果排序 
  101.      * 
  102.      * HQL語句中的排序: 
  103.      *         order by 
  104.      *         asc:升序(預設值) 
  105.      *         desc:降序 
  106.      */  
  107.     @Test  
  108.     public void test4(){  
  109.         Session session = HibernateUtils.openSession();  
  110.         Transaction transaction = session.beginTransaction();  
  111.         // 按聯絡人ID降序排序聯絡人  
  112.         Query query = session.createQuery("from LinkMan order by lkmId desc");  
  113.         @SuppressWarnings("unchecked")  
  114.         List<LinkMan> linkMans = query.list();  
  115.         transaction.commit();  
  116.         for (LinkMan linkMan : linkMans) {  
  117.             System.out.println(linkMan);  
  118.         }  
  119.     }  
  120.   
  121.     /** 
  122.      * 分頁查詢 
  123.      * MySQL中分頁關鍵字: 
  124.      *         Limit 
  125.      * limit的兩個引數: 第一個引數:查詢的開始記錄索引。(它是從0開始的) 
  126.      *                    第二個引數:每次查詢多少條記錄。(它是固定的) 
  127.      * Hibernate中涉及的方法 
  128.      *         setFirstResult(int firstResult):查詢的開始記錄索引 
  129.      *         setMaxResults(int maxResults):每次查詢多少條記錄 
  130.      */  
  131.     @Test  
  132.     public void test5(){  
  133.         Session session = HibernateUtils.getCurrentSession();  
  134.         Transaction transaction = session.beginTransaction();  
  135.         //1.獲取Query物件  
  136.         Query query = session.createQuery("from LinkMan");  
  137.         //2.使用Hibernate提供的方法來設定分頁條件  
  138.         Integer firstResult = 0;  
  139.         Integer maxResults = 2;  
  140.         query.setFirstResult(firstResult);  
  141.         query.setMaxResults(maxResults);  
  142.         //3.執行query物件的方法  
  143.         @SuppressWarnings("unchecked")  
  144.         List<LinkMan> list = query.list();  
  145.         transaction.commit();  
  146.         for (LinkMan linkMan : list) {  
  147.             System.out.println(linkMan);  
  148.         }  
  149.     }  
  150.   
  151.     /** 
  152.      * 統計查詢 
  153.      *       其實就是在HQL語句中使用聚合函式 
  154.      *         count() sum() avg() max() min() 
  155.      *      使用聚合函式查詢時,如果沒有group by,返回的結果集是一行一列的 
  156.      * 
  157.      *  聚合函式都不會計算為null的欄位。 
  158.      *  
  159.      *  count(*)和count(主鍵)是一樣的。 
  160.      */  
  161.     @Test  
  162.     public void test6(){  
  163.         Session session = HibernateUtils.getCurrentSession();  
  164.         Transaction transaction = session.beginTransaction();  
  165.         // 查詢一共有多少個聯絡人  
  166.         Query query = session.createQuery("select count(lkmId) from LinkMan");  
  167.         Long count = (Long) query.uniqueResult();  
  168.         transaction.commit();  
  169.         System.out.println(count);  
  170.     }  
  171.   
  172.     /** 
  173.      * 投影查詢: 
  174.      *      當我們查詢實體物件時,並不需要所有欄位資訊,只查詢部分,但是還想讓他成為一個實體物件。其實就是用部分欄位來投影出整個實體物件。 
  175.      * 使用要求: 
  176.      *     HQL語句: 
  177.      *         寫法必須是  new 實體類名稱(查詢的欄位) 
  178.      *         select new Customer(custId,custName) from Customer 
  179.      *         注意:如果你的實體類在工程中唯一,則可以直接寫類名。如果實體類在工程中不唯一,需要寫全限定類名。 
  180.      *  實體類要求: 
  181.      *      必須在實體類中提供一個相同引數列表的建構函式。 
  182.      *          
  183.      */  
  184.     @Test  
  185.     public void test71(){  
  186.         Session session = HibernateUtils.getCurrentSession();  
  187.         Transaction transaction = session.beginTransaction();  
  188.         // 只獲取客戶的ID和名字,並封裝成客戶物件  
  189.         Query query = session.createQuery("select new Customer(custId, custName) from Customer");  
  190.         @SuppressWarnings("unchecked")  
  191.         List<Customer> customers = query.list();  
  192.         transaction.commit();  
  193.         for (Customer customer : customers) {  
  194.             System.out.println(customer.getCustId() + " " + customer.getCustName());  
  195.         }  
  196.     }  
  197.   
  198.     @Test  
  199.     public void test72(){  
  200.         Session s = HibernateUtils.getCurrentSession();  
  201.         Transaction tx = s.beginTransaction();  
  202.         //1.獲取Query物件  
  203.         Query query = s.createQuery("select custId,custName from Customer ");  
  204.         //2.執行query物件的方法  
  205.         @SuppressWarnings("unchecked")  
  206.         List<Object[]> list = query.list();  
  207.         tx.commit();  
  208.         for(Object[] os : list){  
  209.             System.out.println("----------每個陣列中的內容------------");  
  210.             for(Object o : os){  
  211.                 System.out.println(o);  
  212.             }  
  213.         }  
  214.     }  
  215.   
  216.     /** 
  217.      * 左外連線查詢和迫切左外連線查詢的區別 
  218.      * 區別: 
  219.      *     返回的結果集不一樣。在實際開發中用的不多,此處講解就是為了說明他們之間的區別 
  220.      * 注意: 
  221.      *     Hibernate中沒有右外連線 
  222.      * 
  223.      * Hibernate左外連線返回的資料:    
  224.      *         返回的是一個有Object陣列組成的List集合,該陣列中有兩個物件。一個是主表實體,一個是從表實體。 
  225.      *         主表實體有可能重複 
  226.      */  
  227.     //左外連線查詢  
  228.     @Test  
  229.     public void test81(){  
  230.         Session session = HibernateUtils.getCurrentSession();  
  231.         Transaction transaction = session.beginTransaction();  
  232.         //1.獲取Query物件  
  233.         //sql語句的左外:select * from cst_customer c left outer join cst_linkman l on c.cust_id = l.lkm_cust_id;  
  234.         Query query = session.createQuery("from Customer c left join c.linkMans");  
  235.         //2.執行query物件的方法  
  236.         @SuppressWarnings("unchecked")  
  237.         List<Object[]> list = query.list();  
  238.         transaction.commit();  
  239.         for (Object[] objects : list) {  
  240.             System.out.println("------一組物件-------");  
  241.             for (Object object : objects) {  
  242.                 System.out.println(object);  
  243.             }  
  244.         }  
  245.     }  
  246.   
  247.     /** 
  248.      * 迫切左外連線查詢: 
  249.      *         要想使用迫切,需要在查詢HQL語句中加入一個關鍵字:fetch 
  250.      * Hibernate迫切左外連線返回的資料: 
  251.      *         返回的是左表實體物件的List集合,並且左表中對應右表的欄位已經被填充 
  252.      */  
  253.     @Test  
  254.     public void test82(){  
  255.         Session session = HibernateUtils.getCurrentSession();  
  256.         Transaction transaction = session.beginTransaction();  
  257.         //1.獲取Query物件  
  258.         Query query = session.createQuery("from Customer c left join fetch c.linkMans");  
  259.         //2.執行query物件的方法  
  260.         @SuppressWarnings("unchecked")  
  261.         List<Customer> customers = query.list();  
  262.         transaction.commit();  
  263.         for (Customer customer : customers) {  
  264.             System.out.println("------一組物件-------");  
  265.             System.out.println(customer);  
  266.             for (LinkMan linkMan : customer.getLinkMans()) {  
  267.                 System.out.println(linkMan);  
  268.             }  
  269.             System.out.println("");  
  270.         }  
  271.     }  
  272.   
  273.     /** 
  274.      * 使用HQL進行更新操作 
  275.      */  
  276.     @Test  
  277.     public void test9(){  
  278.         Session session = HibernateUtils.getCurrentSession();  
  279.         Transaction transaction = session.beginTransaction();  
  280.         //1.獲取Query物件  
  281.         Query query = session.createQuery("update Customer set custName = ? where custId = ?");  
  282.         query.setString(0"XX公司");  
  283.         query.setString(1"1");  
  284.         //2.執行query物件的方法  
  285.         int result = query.executeUpdate();  
  286.         transaction.commit();  
  287.         System.out.println(result);  
  288.     }  
  289. }  


QBC查詢
     QBC(Query By Criteria)是Hibernate提供的另一種檢索物件的方式,它主要由Criteria 介面、Criterion介面和Expression類組成 。Criteria介面是Hibernate API中的一個查詢介面,它需要由session進行建立。Criterion是Criteria的查詢條件,在Criteria中提供了add(Criterion criterion)方法來新增查詢條件。
     涉及的物件:
          Criteria
          DetachedCriteria
     獲取的方式:
          session.createCriteria(Class clazz);引數指的是要查詢的位元組碼
     新增條件的方法:
          Criteria的add方法
     新增條件涉及的物件:
          Restrictions

Restrictions類提供的方法
方法名
說明
Restrictions.eq
等於
Restrictions. allEq
使用 Map ,使用key/value進行多個等於的比較
Restrictions.gt
大於>
Restrictions.ge
大於等於>=
Restrictions.lt
小於
Restrictions.le
小於等於<=
Restrictions.between
對應 SQL 的 between 子句
Restrictions.like
對應 SQL 的 like 子句
Restrictions.in
對應 SQL 的 IN 子句
Restrictions.and
and 關係
Restrictions.or
or 關係
Restrictions.sqlRestriction
SQL 限定查詢


離線條件檢索
     DetachedCriteria 翻譯為離線條件查詢,因為它是可以脫離Session來使用的一種條件查詢物件,我們都知道Criteria物件必須由Session物件來建立。那麼也就是說必須先有Session才可以生成Criteria物件。而DetachedCriteria物件可以在其他層對條件進行封裝。
     這個物件也是比較有用的,尤其在SSH整合以後這個物件經常會使用 。它的主要優點是做一些特別複雜的條件查詢的時候,往往會在WEB層向業務層傳遞很多的引數,業務層又會將這些引數傳遞給DAO層。最後在DAO中拼接SQL完成查詢。有了離線條件查詢物件後,那麼這些工作都可以不用關心了,我們可以在WEB層將資料封裝好,傳遞到業務層,再由業務層傳遞給DAO完成查詢。

測試QBC檢索方式
[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3.   
  4. import java.util.List;  
  5.   
  6. import org.hibernate.Criteria;  
  7. import org.hibernate.Session;  
  8. import org.hibernate.Transaction;  
  9. import org.hibernate.criterion.DetachedCriteria;  
  10. import org.hibernate.criterion.Order;  
  11. import org.hibernate.criterion.Projections;  
  12. import org.hibernate.criterion.Restrictions;  
  13. import org.junit.Test;  
  14.   
  15. import com.pc.hibernate.domain.Customer;  
  16. import com.pc.hibernate.domain.LinkMan;  
  17. import com.pc.hibernate.utils.HibernateUtils;  
  18.   
  19. /** 
  20.  * Hibernate中的查詢方式: 
  21.  *         QBC查詢: 
  22.  *             Query By Criteria  它是一種更加物件導向的查詢方式。 
  23.  *             它把查詢條件都用方法封裝了。裡面的引數全都需要使用實體類的屬性名稱。 
  24.  *         涉及的物件: 
  25.  *             Criteria 
  26.  *             DetachedCriteria 
  27.  *         獲取的方式: 
  28.  *             session.createCriteria(Class clazz);引數指的是要查詢的位元組碼 
  29.  *         新增條件的方法: 
  30.  *              Criteria的add方法。 
  31.  *         新增條件涉及的物件: 
  32.  *             Restrictions 
  33.  * 
  34.  * @author Switch 
  35.  */  
  36. public class TestQBCQuery {  
  37.     /** 
  38.      * 基本查詢:查詢所有 
  39.      * 
  40.      * 需求: 
  41.      *     查詢所有客戶 
  42.      */  
  43.     @Test  
  44.     public void test1(){  
  45.         Session session = HibernateUtils.getCurrentSession();  
  46.         Transaction tx = session.beginTransaction();  
  47.         //1.獲取Criteria物件  
  48.         Criteria criteria = session.createCriteria(Customer.class);  
  49.         //2.執行list方法,得到結果集  
  50.         @SuppressWarnings("unchecked")  
  51.         List<Customer> customers = criteria.list();  
  52.         tx.commit();  
  53.         for (Customer customer : customers) {  
  54.             System.out.println(customer);  
  55.         }  
  56.     }  
  57.   
  58.     /** 
  59.      * 條件查詢 
  60.      *     需求:查詢客戶級別是23的,客戶名稱帶有集字的 
  61.      */  
  62.     @Test  
  63.     public void test2(){  
  64.         Session session = HibernateUtils.getCurrentSession();  
  65.         Transaction tx = session.beginTransaction();  
  66.         //1.獲取Criteria物件  
  67.         Criteria criteria = session.createCriteria(Customer.class);  
  68.         // 新增條件  
  69.         criteria.add(Restrictions.eq("custLevel""23"));  
  70.         criteria.add(Restrictions.like("custName""%集%"));  
  71.         //2.執行list方法,得到結果集  
  72.         @SuppressWarnings("unchecked")  
  73.         List<Customer> customers = criteria.list();  
  74.         tx.commit();  
  75.         for (Customer customer : customers) {  
  76.             System.out.println(customer);  
  77.         }  
  78.     }  
  79.   
  80.     /** 
  81.      * 分頁查詢 
  82.      * 
  83.      * 涉及的方法: 
  84.      *         setFirstResult(int firstResult); 
  85.      *         setMaxResults(int maxResults); 
  86.      * 含義和HQL是一模一樣的 
  87.      */  
  88.     @Test  
  89.     public void test3(){  
  90.         Session session = HibernateUtils.getCurrentSession();  
  91.         Transaction tx = session.beginTransaction();  
  92.         //1.獲取Criteria物件  
  93.         Criteria criteria = session.createCriteria(Customer.class);  
  94.         criteria.setFirstResult(0);  
  95.         criteria.setMaxResults(2);  
  96.         //2.執行list方法,得到結果集  
  97.         @SuppressWarnings("unchecked")  
  98.         List<Customer> customers = criteria.list();  
  99.         tx.commit();  
  100.         for (Customer customer : customers) {  
  101.             System.out.println(customer);  
  102.         }  
  103.     }  
  104.   
  105.     /** 
  106.      * 統計查詢: 
  107.      *      使用QBC來新增聚合函式 
  108.      * 
  109.      * count() avg() min() max() sum() 
  110.      * 
  111.      * 涉及的方法: 
  112.      *         setProjections(Projection p ); 它可以加查詢語句的結構。 
  113.      * 涉及的類: 
  114.      *         Projections 
  115.      *         該類中提供了一些靜態方法 
  116.      */  
  117.     @Test  
  118.     public void test4(){  
  119.         Session session = HibernateUtils.getCurrentSession();  
  120.         Transaction tx = session.beginTransaction();  
  121.         //1.獲取Criteria物件  
  122.         Criteria criteria = session.createCriteria(Customer.class);  
  123.         criteria.setProjection(Projections.count("custId"));  
  124.   
  125.         //2.執行uniqueResult方法,得到結果  
  126.         Long result = (Long) criteria.uniqueResult();  
  127.         tx.commit();  
  128.   
  129.         System.out.println(result);  
  130.     }  
  131.   
  132.     /** 
  133.      * 排序查詢 
  134.      * 
  135.      * 涉及方法: 
  136.      *       Criteria的addOrder方法。該方法需要一個Order物件作為引數 
  137.      * Order物件有兩個方法: 
  138.      *         desc(String propertyName):按照指定的屬性名稱,倒序排序。 
  139.      *         asc(String propertyName):按照自頂的屬性名稱,正序排序。 
  140.      */  
  141.     @Test  
  142.     public void test5(){  
  143.         Session session = HibernateUtils.getCurrentSession();  
  144.         Transaction tx = session.beginTransaction();  
  145.         //1.獲取Criteria物件  
  146.         Criteria criteria = session.createCriteria(LinkMan.class);  
  147.         criteria.addOrder(Order.desc("lkmId"));  
  148.   
  149.         //2.執行list方法,得到結果集  
  150.         @SuppressWarnings("unchecked")  
  151.         List<LinkMan> linkMans = criteria.list();  
  152.   
  153.         tx.commit();  
  154.         for (LinkMan linkMan : linkMans) {  
  155.             System.out.println(linkMan);  
  156.         }  
  157.     }  
  158.   
  159.   
  160.     /** 
  161.      * 離線查詢: 
  162.      *      線上物件: 
  163.      *         Criteria物件。它的獲取必須要一個可用的Session來建立。如果Session不能用,則不能建立Criteria。 
  164.      *         我們使用Criteria進行的查詢就是線上查詢。 
  165.      *      離線物件: 
  166.      *         建立DetachedCriteria不需要一個可用的Session。 
  167.      *         用DetachedCriteria進行的查詢就叫做離線查詢 
  168.      * 涉及的物件 
  169.      *         DetachedCriteria 
  170.      * 如何獲取 
  171.      *         DetachedCriteria.forClass(Class clazz);引數的含義:要查詢的實體類 
  172.      * 如何設定查詢條件: 
  173.      *         和Criteria是一樣的 
  174.      * 
  175.      * 在實際開發中:多條件查詢用此種方式 
  176.      */  
  177.   
  178.     //Servlet的方法  
  179.     @Test  
  180.     public void doGet(){  
  181.         //1.獲取請求引數  
  182.         String custLevel = "23";  
  183.         String custName = "集";  
  184.         //2.查詢所有客戶  
  185.         DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);  
  186.         dCriteria.add(Restrictions.eq("custLevel", custLevel));  
  187.         dCriteria.add(Restrictions.like("custName""%"+custName+"%"));  
  188.   
  189.         List<Customer> cs = servicefindAllCustomer(dCriteria);  
  190.   
  191.         for(Customer c : cs){  
  192.             //3.存入請求域中  
  193.             //4.轉向列表頁面  
  194.             System.out.println(c);  
  195.         }  
  196.     }  
  197.   
  198.     //Service的方法  
  199.     public List<Customer> servicefindAllCustomer(DetachedCriteria dCriteria){  
  200.         return daofindAllCustomer(dCriteria);  
  201.     }  
  202.   
  203.     //Dao中的方法  
  204.     public List<Customer> daofindAllCustomer(DetachedCriteria dCriteria){  
  205.         Session s = HibernateUtils.getCurrentSession();  
  206.         Transaction tx = s.beginTransaction();  
  207.         //1.把離線物件啟用  
  208.         Criteria c = dCriteria.getExecutableCriteria(s);  
  209.         //3.執行list方法,得到結果集  
  210.         @SuppressWarnings("unchecked")  
  211.         List<Customer> list = c.list();  
  212.         tx.commit();  
  213.         return list;  
  214.     }  
  215. }  


原生SQL查詢
     採用HQL或QBC檢索方式時,Hibernate生成標準的SQL查詢語句,適用於所有的資料庫平臺,因此這兩種檢索方式都是跨平臺的。但有的應用程式可能需要根據底層資料庫的SQL方言,來生成一些特殊的查詢語句。在這種情況下,可以利用Hibemate提供的原生SQL檢索方式 。
     原生SQL查詢時通過SQLQuery sqlQuery = session.createSQLQuery(String sql)來實現的,因為操作方式就是SQL語句,故不再介紹。
[java] view plain copy
  1. /** 
  2.  * SQLQuery 它使用的是原始的SQL語句查詢 
  3.  */  
  4. @Test  
  5. public void test3() {  
  6.     Session s = HibernateUtils.getCurrentSession();  
  7.     Transaction tx = s.beginTransaction();  
  8.     // 1.獲取SQLQuery物件  
  9.     SQLQuery sqlquery = s.createSQLQuery("select * from cst_customer");// 引數是SQL語句  
  10.     // 2.執行sqlquery的方法,返回結果集  
  11.     /* 
  12.      * List<Object[]> list = sqlquery.list(); for(Object[] os : list){ 
  13.      * System.out.println( 
  14.      * "-------------每出現一行分割線,表示外層迴圈執行了一次-------------------"); <br/> 
  15.      * for(Object o : os){ System.out.println(o); } } 
  16.      */  
  17.     // 新增實體類位元組碼,把查詢結果轉成實體類物件  
  18.     sqlquery.addEntity(Customer.class);  
  19.     List<Customer> cs = sqlquery.list();  
  20.     for (Customer c : cs) {  
  21.         System.out.println(c);  
  22.     }  
  23.     tx.commit();  
  24. }  



該博文使用的Hibernate配置檔案和對映檔案


Customer.hbm.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC  
  3.   
  4.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  5.     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
  6. <!--  
  7. 1、匯入dtd約束  
  8.      在Hibernate的核心jar包中:hibernate-mapping-3.0.dtd  
  9. 2、編寫配置檔案  
  10.           實體類和資料庫表的對應關係  
  11.           實體類中屬性和表的欄位的對應關係  
  12.  -->  
  13. <hibernate-mapping package="com.pc.hibernate.domain">  
  14.      <!-- class標籤:  
  15.               作用:用於配置實體類和表之間的對應關係  
  16.               屬性:  
  17.                    name:實體類的名稱。它應該寫全限定類名  
  18.                    table:資料庫表的名稱  
  19.      -->  
  20.      <class name="Customer" table="cst_customer" lazy="true" batch-size="3">  
  21.           <!-- id標籤:  
  22.                    作用:對映主鍵  
  23.                    屬性:  
  24.                         name:實體類的屬性名稱  
  25.                         column:資料庫表的欄位名稱  
  26.                         type:主鍵的型別  
  27.           -->  
  28.           <id name="custId" column="cust_id" type="java.lang.Long">  
  29.               <!-- generator標籤:  
  30.                         作用:主鍵的生成方式  
  31.                         屬性:  
  32.                              class:指定方式  
  33.                              取值:native  
  34.                                   含義:使用本地資料庫的自動增長能力。  
  35.               -->  
  36.   
  37.               <generator class="native"/>  
  38.           </id>  
  39.           <!-- property標籤:  
  40.                    作用:對映其他欄位  
  41.                    屬性:  
  42.                         name:實體類的屬性名稱  
  43.                         column:資料庫表的欄位名稱  
  44.                         type:欄位的型別  
  45.                         length:資料庫中對應列的長度  
  46.           -->  
  47.           <property name="custName" column="cust_name" type="java.lang.String" length="32"/>  
  48.           <property name="custSource" column="cust_source" type="java.lang.String" length="32"/>  
  49.           <property name="custIndustry" column="cust_industry" type="java.lang.String" length="32"/>  
  50.           <property name="custLevel" column="cust_level" type="java.lang.String" length="32"/>  
  51.           <property name="custAddress" column="cust_address" type="java.lang.String" length="128"/>  
  52.           <property name="custPhone" column="cust_phone" type="java.lang.String" length="64"/>  
  53.   
  54.           <!-- 配置一對多 -->  
  55.           <set name="linkMans" inverse="false" cascade="save-update" batch-size="4" lazy="true" fetch="select">  
  56.               <key column="lkm_cust_id" />  
  57.               <one-to-many class="LinkMan"/>  
  58.           </set>  
  59.      </class>  
  60. </hibernate-mapping>  


LinkMan.hbm.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC  
  3.   
  4.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  5.     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
  6. <hibernate-mapping package="com.pc.hibernate.domain">  
  7.      <class name="LinkMan" table="cst_linkman">  
  8.           <id name="lkmId" column="lkm_id" type="java.lang.Long">  
  9.               <generator class="native" />  
  10.           </id>  
  11.           <property name="lkmName" column="lkm_name" type="java.lang.String" length="16"/>  
  12.           <property name="lkmGender" column="lkm_gender" type="java.lang.String" length="10"/>  
  13.           <property name="lkmPhone" column="lkm_phone" type="java.lang.String" length="16"/>  
  14.           <property name="lkmMobile" column="lkm_mobile" type="java.lang.String" length="16"/>  
  15.           <property name="lkmEmail" column="lkm_email" type="java.lang.String" length="64"/>  
  16.           <property name="lkmPosition" column="lkm_position" type="java.lang.String" length="16"/>  
  17.           <property name="lkmMemo" column="lkm_memo" type="java.lang.String" length="512"/>  
  18.   
  19.           <!-- 配置多對一 -->  
  20.           <many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update" lazy="proxy" fetch="select"/>  
  21.      </class>  
  22. </hibernate-mapping>  

hibernate.cfg.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC  
  3.      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  4.      "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">  
  5. <!-- 1、匯入dtd約束 在hibernate核心jar包中:hibernate-configuration-3.0.dtd 2、編寫配置檔案 -->  
  6. <hibernate-configuration>  
  7.      <!-- 配置SessionFactory -->  
  8.      <!-- 建立SessionFactory需要3部分資訊。 而配置檔案中要寫哪些配置,我們可以翻閱資料。 -->  
  9.      <!-- 第一部分:連線資料庫的基本資訊,第二部分:hibernate的基本配置,第三部分:對映檔案的位置 -->  
  10.      <session-factory>  
  11.           <!-- 1、連線資料庫的基本資訊 -->  
  12.           <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  13.           <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mycrm</property>  
  14.           <property name="hibernate.connection.username">root</property>  
  15.           <property name="hibernate.connection.password">123456</property>  
  16.   
  17.           <!-- 資料庫的方言 -->  
  18.           <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  19.   
  20.           <!-- 2、hibernate的基本配置 -->  
  21.           <!-- 是否顯示SQL語句 -->  
  22.           <property name="hibernate.show_sql">true</property>  
  23.           <!-- 是否格式化顯示SQL語句 -->  
  24.           <!-- <property name="hibernate.format_sql">true</property> -->  
  25.           <!-- 採用何種策略來建立表結構: -->  
  26.           <!-- update:檢查表結構和實體類對映檔案的變化,如果發現對映檔案和表結構不一致,更新表結構。 -->  
  27.           <!-- 注意:hibernate不能建立資料庫,只能在有資料庫的情況下建立表結構。 -->  
  28.           <property name="hibernate.hbm2ddl.auto">update</property>  
  29.   
  30.           <!-- 配置hibernate使用連線池:告知Hibernate使用連線池的廠商 -->  
  31.           <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
  32.   
  33.           <!-- 配置把Session繫結到當前執行緒上,從而保證一個執行緒只有一個Session -->  
  34.           <property name="hibernate.current_session_context_class">thread</property>  
  35.   
  36.           <!-- 3、對映檔案的位置 -->  
  37.           <mapping resource="com/pc/hibernate/domain/Customer.hbm.xml" />  
  38.           <mapping resource="com/pc/hibernate/domain/LinkMan.hbm.xml" />  
  39.      </session-factory>  
  40. </hibernate-configuration>  

相關文章