1. 程式人生 > >Hibernate HQL基礎

Hibernate HQL基礎

一、Query介面

1.org.hibernate.Query介面定義有執行查詢的方法(該方法完成HQL語句的解析與執行過程,並返回查詢的結果。就像SQL語句沒有jdbc介面,它也就是普通的字串變數,HQL語句也一樣,編寫好的HQL語句也就是一個普通的字串變數,而hibernate框架就負責解析HQL語句,然後根據配置資訊生成相應的SQL語句來執行資料庫的查詢操作,那麼完成這個過程依靠的就是Query介面);
2.Query介面支援方法鏈程式設計風格,使得程式程式碼更為簡潔(方法鏈程式設計:呼叫方法後,返回的結果依然是呼叫這個方法的物件,可以在呼叫方法後直接呼叫該物件的其他方法,這樣可以使用一個程式語句完成多個方法的呼叫與執行。在Query介面中,方法鏈程式設計使用最多的場景是查詢引數的動態設定,特別是多個引數的設定)
3.Query例項的建立:
  a.Session的createQuery()方法建立Query例項
  b.createQuery方在呼叫時需要傳遞一個引數(即要查詢的HQL語句),createQuery(hql)
4.Query執行查詢
  a.Query介面的list()方法執行HQL查詢
  b.list()方法返回結果資料型別為java.util.List,List集合中存放符合查詢條件的持久化物件

 

二、HQL語句

HQL語句中可以直接使用"from 類名"就可以查詢到此類對應資料庫表中的所有資訊.不需要像sql那樣"select*from 表名",直接"form 類名"即可.
list()方法返回的是HQL語句所查詢的類的持久化物件的集合.所以一般定義一個帶泛型的List集合來儲存.
  Query query=session.createQuery("from Student");
  List<Student> list=query.list();
  for(List l:list){
    System.out.println(l);
  }

注意:HQL是面向物件的查詢,查詢的是類,不像sql一樣,直接查詢表.因此在from 後面加的是類名(注意大小寫).list()方法會根據查詢的類名然後去對映檔案中找到相應的資料庫表,此時便把HQL語句解析成sql語句.再查詢到相應的記錄,最後返回記錄的持久化物件的集合.
對於Hiberante5.2.4,query.list()方法已經棄用:
  public void selletTest() {
    String hql = "from Seller";
    Query query = session.createQuery(hql, Seller.class);
    // 注:hibernate5.2.4已經棄用了query.list()方法
    List<Seller> sellers = query.getResultList();
    for (Seller seller : sellers) {
      System.out.println(seller);
    }
  }

 

*****HQL語句形式*******
select子句:用來指定查詢結果中的物件和屬性,並指定以何種資料型別返回 (在最前面)
from子句:用來指定hql語句的查詢目標,即對映配置的持久化類及其屬性
where子句:邏輯表示式,用來設定查詢條件,限制返回結果和範圍
group by子句:分組查詢語句
having子句:對分組進行限制條件設定
order by子句:用來指定查詢結果中的例項物件的排序
注:From子句在HQL語句中不可或缺的組成部分,一個最簡單的HQL語句形式只要有from就可以了,其他的子句都可以省略,這點與SQL語句不同

**********初學HQL注意的問題***********
1、HQL是面向物件的查詢語言,其查詢主體是持久化類及其屬性,而SQL查詢主體是資料庫表與表的欄位;HQL對Java類與屬性大小寫不敏感、SQL語句對大小寫敏感;
2、HQL與SQL在形式上非常相似,特別是HQL在設計上儘量符合之前SQL開發人員的開發習慣,在使用上非常容易與SQL混淆,但是我們不能被表象所迷惑,要認清本質;
3、HQL對關鍵字不區分大小寫,比如之前提到的幾個SQL子句其中的關鍵字,from,where,group by,having,order by...等,只要拼寫正確,大小寫並不重要,但是為了程式碼的可讀性與美觀性,習慣上對HQL的所有關鍵字小寫

 

三、查詢物件——from子句

from子句:
from子句是HQL語句的最簡形式,換句話說,HQL語句只需要from子句就可以執行查詢了,這是為什麼呢?
這是因為from子句指定了HQL語句查詢的主體----對映配置的持久化類及其屬性,當我們編寫的HQL語句只有from子句的時候,HQL框架預設就是查詢該持久化類的所有例項以及該持久化類對映配置的資訊,當HQL框架將HQL解析成SQL時,就會查詢該持久化類對映的資料表中的所有對映欄位資訊,並將返回的查詢結果封裝成該持久化類的list集合

hibernate預設的是懶載入狀態,預設狀態下是不查詢外來鍵資訊所對應的資料的,只有當我們需要的時候才會根據具體的需要進行查詢。在控制檯輸出語句中,已經輸出過的外來鍵所對應的持久類查詢sql語句不再重複輸出。

from子句中持久化類的引用:
1、不需要引入持久化類的全限定名(如from com.imooc.model.Seller),直接引入類名(from Seller)即可
2、我們知道在java環境中一定要指明全限定名,這樣java環境才知道去獲取這個類,而HQL語句中之所以可以省略,是因為auto-import自動引入預設情況。hibernate框架中,在解析HQL語句時,會根據對映配置資訊自動完成持久化類的匯入,這樣的方式更加方便,也更加符合程式設計師的程式設計習慣。
3、在from子句中全限定名的引用與直接引入類名是一樣,並不會報錯!

from子句中別名的引用:
1.為被查詢的類指定別名
2.在HQL語句其他部分通過別名引用該類
3.別名命名習慣,參考Java變數的命名習慣
為類指定別名:from Seller as s/from Seller s,要保留程式碼的可讀性

 

四、選擇——select子句

1.以Object[]形式返回選擇的屬性:
2.以List形式返回選擇的屬性
3.以map形式返回選擇的屬性
4.以自定義型別返回選擇的屬性
5.獲取獨特的結果-distinct關鍵字

hql中查詢一個欄位 返回的是List<Object>物件,查詢多個欄位返回的是List<Object[]>,查詢所有欄位返回的是List<實體類>物件,建議多使用別名來區分不同表中的相同欄位
  String hql="select s.name,s.tel,s.address,s.star from Seller s ";
  Query query=session.createQuery(hql);
  List<Object[]> list=query.list();
  for (Object[] objects : list) {
    System.out.println(" name : "+objects[0]);
    System.out.println(" tel : "+objects[1]);
    System.out.println(" address : "+objects[2]);
    System.out.println(" star : "+objects[3]);
    System.out.println("");
  }

選擇-select子句,作用:指定只需要的查詢資訊,提高程式的執行效率
1.以Object[]形式返回選擇的屬性:
注意:hql的select查詢語句中,如果指定了多個查詢欄位,則返回的是一個Object[]陣列,然而如果只指定了一個查詢欄位,則返回的是一個Object物件。
  String hql = "select s.name,s.tel from Seller s";
  Query query = session.createQuery(hql);
  List<Object[]> sellers = query.list();
  for(Object[] objs:sellers){
    System.out.println("name:"+objs[0]);
    System.out.println("tel:"+objs[1]);
  }(如果是單個查詢欄位的話就只需要把上面的Object[]中的[]去掉,列印輸出時不需要指明下標)

2.以List形式返回選擇的屬性
  String hql = "select new list(s.name,s.tel,s.address) from Seller s";
  ...
  List<List>lists=query.getResultList();

3.以map形式返回選擇的屬性
  注意:key為索引值,是字串型別(map.get("0")),如果給查詢欄位指定了別名,則以該別名為key的值,使用Map集合時考慮使用別名獲取屬性資訊  
  String hql = "select new map(s.name,s.tel,s.address) from Seller s";

4.以自定義型別返回選擇的屬性
  (1)持久化類中定義對應的構造器
  (2)select子句中呼叫定義的構造器
  注意:預設無參構造器是需要的,因為,在Hibernate沒有指定的查詢的放回集合時候,Hibernate會自動去找預設構造器,如果不存在,則會出現異常
  String hql = "select new Seller(s.name,s.tel,s.address) from Seller s";

5.獲取獨特的結果-distinct關鍵字
  distinct關鍵字 消除查詢過程中重複的元素
  String hql = "select distinct s.sex from Seller s";

 

五、限制——where子句

1.比較運算
2.範圍運算
3.字串模式匹配
4.邏輯運算
5.集合運算
6.在HQL中使用+、-、*、/運算子
7.查詢單個物件(uniqueResult方法)

比較運算子:=、<>、<、>、>=、<=
null值判斷——is [not] null
HQL中的x=null會被解析為SQL中的x is null、x<>null會被解析為SQL中的x is not null

範圍運算:
1.[not] in(列表)(列表既可以明確指出,也可以是子查詢)
2.[not] between 值1 and 值2
//尋找價格(不)是4000或5000的商品
String hql="from Commodity c where c.price (not) in (5000,4000)";
//尋找價格(不在)在200到4000的商品
String hql1="from Commodity c where c.price (not) between 200 and 4000";

字串模式匹配:
1.like 關鍵字
2.萬用字元:% 匹配任意個字元,_ 匹配一個字元

邏輯運算子
1.and(邏輯與)、or(邏輯或)
2.not(邏輯非)
String hql="from Commodity c where c.price between 100 and 4000 and c.category like '%電腦%'";
String hql1="from Commodity c where c.price between 100 and 4000 or c.category like '%電腦%'";

集合運算:
1、is [not] empty,集合【不】為空,不包含任何元素;對應SQL的exists運算
2、member of 元素屬於集合 ;對應SQL的in運算。

四則運算
1.HQL語句中也可以使用+ - * / 四則運算
2.四則運算可以在where子句和select子句中使用

查詢單個物件:
query介面的uniqueResult方法
1.該方法的返回是例項物件而不是返回集。
2.需要注意的是我們必須要通過where將查詢得到的記錄只剩下一條或者查詢不到。如果有一條以上就會發生異常。

 

六、排序——order by子句

asc升序,desc降序。
多個排序規則用“,”隔開;表示前一個規則中排序條件相同則用後一個排序規則