程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate HQL查詢簡介

Hibernate HQL查詢簡介

編輯:關於JAVA

傳統的SQL語言采用的是結構化的查詢方法,而這種方法對於查詢以對象形式存在的數據卻無能為力。幸運的是,Hibernate為我們提供了一種語法類似於SQL的語言,Hibernate查詢語言(HQL),和SQL不同的是,HQL是一種面向對象的查詢語言,它可以查詢以對象形式存在的數據。因此,本文就HQL如何工作以及如何使用HQL展開了深入的討論。

SQL本身是非常強大的。當SQL的這種強大和處理面向對象數據的能力相結合時,就產生了HQL。和SQL一樣,HQL提供了豐富的查詢功能,如投影查詢、聚合函數、分組和約束。任何復雜的SQL都可以映射成HQL。

本文的第一部分將討論HQL的簡單用法。第二部分將討論在HQL中如何根據上下文關系進行查詢。在第三部分將以一個例子來說明如何在實際應用中使用HQL。

進入HQL世界

一個ORM框架是建立在面向對象的基礎上的。最好的例子是Hibernate如何提供類SQL查詢。雖然HQL的語法類似於SQL,但實際上它的查詢目標是對象。HQL擁有面向對象語言的所有的特性,這其中包括多態、繼承和組合。這就相當於一個面向對象的SQL,為了提供更強大的功能,HQL還提供了很多的查詢函數。這些函數可以被分為四類:

1.投影函數

2.約束函數

3.聚合函數

4.分組函數

使用HQL可以建立簡單的查詢,也可以建立更復雜的查詢。在本文中並不討論那些非常復雜的查詢,如含有子查詢和很多連接的查詢。本文只討論連接兩個表的查詢。現在讓我們開始接近HQL吧!

投影

如謂投影,就是一個可以訪問的對象或對象的屬性。在HQL中,可以使用from和select子句來完成這個工作。

from子句返回指定的類的所有實例。如from Order將返回Order類的所有實例。換句話說,以上的查詢相當於以下的SQL語句:

select * from order

from 是最簡單的查詢子句。from後面可以跟一個或多個類名(類名也可以帶有別名)。為了得到Order和Product的所有實例,可以使用如下的查詢:

from Order, Product

和類名一樣,別名也可以在from後使用,如下代碼如示:

from Order as o, Product p

當查詢很復雜時,加入別名可以減少語句的長度。我們可以看看如下的SQL語句:

select o.*, p.* from order o, product p where o.order_id = p.order_id

我們可以很容易看出,上面的查詢是一對多的關系。在HQL中相當於一個類中包含多個其它類的實例。因此,以上的SQL寫成HQL就是:

from Order as o inner join o.products as product

現在讓我們考慮另外一個從表中得到指定屬性的情況。這就是最常用的select子句。這在HQL中的工作方式和SQL中一樣。而在HQL中,如果只是想得到類的屬性的話,select語句是最後的選擇。以上的SQL可以使用select子句改成如下的HQL語句:

select product from Order as o inner join o.products as product

以上的HQL語句將返回Order中的所有Products實例。如果要得到對象的某一個屬性,可以將HQL語句寫成如下的形式:

select product.name from Order as o inner join o.products as product

如果要得到多個對象的屬性,可以將HQL語句寫成如下形式:

select o.id, product.name from Order as o inner join o.products as product

接下來,我們將進入下一個議題。假設我們需要根據某些條件得到數據。那麼以上所述的HQL語句將無法滿足需求。為了達到這一目的,我們就要用到下面將要討論的約束子句。

約束

從以上可知,投影返回的是所有的數據。但在大多數時候我們並不需要這麼多數據。這就需要對數據進行過濾。在HQL中過濾數據的子句和SQL一樣,也是where。它的語法類似於SQL,通過where子句,可以對行進行過濾。我們可以看看下面的SQL語句:

select * from orders where id = ‘1234’

這條查詢語句返回了id等於1234的所有的字段。和這條SQL對等的是下面的HQL語句:

select o from Order o where o.id=’1234’

從以上兩條語句可以看出,它們的where子句非常相似。而它們唯一的不同是SQL操作的是記錄,而HQL操作的是對象。在HQL中,除了where子句可以過濾數據外,having子句也可以做到這一點(關於having子句的詳細內容我將在分組部分討論)。投影和約束是兩個基本的操作,這兩個操作再加上聚合函數的話,那HQL將變得更加強大。下面我們就來討論什麼是聚合。

聚合

上述的查詢都是將每一個記錄(對象)當做一個單位,而如果使用聚合,可以將一類記錄(對象)當做一個單位。然後再對每一類的記錄(對象)進行一系列地操作,如對某一列取平均值、求和、統計行數等等。HQL支持以下的聚合函數:

1.avg(…), sum(…)

2.min(…), max(…)

3.count(*), count(…), count(distinct…), count(all…)

以上的聚合函數都返回數值類型。這些操作都可以在select子句中使用,如下所示:

select max(o.priceTotal) + max(p.price) from Order o join o.products p group by o.id

以上的HQL語句返回了兩個值的和:orders表中的priceTotal的最大值和products表中的price的最大值之和。我們還可以使用having子句對分組進行過濾。如我們想按id統計priceTotal小於1000的數量可按如下的HQL語句去實現:

select count(o) from Order o having o.priceTotal < 1000 group by o.id

我們還可以將聚合函數和having子句一起使用。如我們要按products表的id統計price小於amount的平均數的產品數量,HQL語句如下:

select count(p) from Product p having p.price < avg(amount) group by p.id

從上面的一系列的HQL語句可以看出,所有通過SQL實現的,都可以通過HQL來實現。

分組

在上一部分,已經涉及到了分組的概念。分組操作的是行的集合。它根據某一列(屬性)對記錄集進行分組。這一切是通過group子句實現的。如下的例子描述了group子句的一般用法。

select count(o) from Order o having o.priceTotal >= 1200 and o.priceTotal <= 3200 group by o.id

HQL中的分組和SQL中的分組類似。總之,除了一些對SQL的特殊擴展外,其它所有的SQL功能都可以使用HQL描述。在接下來的部分,讓我們舉例說明如何在java中使用HQL。

在java中使用HQL

到現在為止,我們已經學習了HQL的基本用法。接下來我們舉一個例子來說明如何在Java中使用HQL。下面的例子只給出了主要的部分,由於本文只是討論HQL的用法,因此,關於Hibernate的一些設置和在main()函數中調用Hibernate的部分並未給出,讀者可以參考相關的文當。現在讓我們看看下面的例子。

下面是必須引用的包

import java.util.List;
import org.hibernate.*;
import org.hibernate.cfg.*
import com.Order;

下面是類的聲明

public class MyOrder
{
… …
}

下面讓我們來實現MyOrder類的構造函數

public class MyOrder
{
SessionFactory sf;
public MyOrder()
{
Configuration cfg = new Configuration().addClass(Order.class);
sf = cfg.buildSessionFactory();
}
… …
}

下面的getOrder函數根據priceTotal的區間值返回Order對象。

public class MyOrder
{
….….
public Order getOrder(String lower, String upper)
{
// 打開一個會話
Session sess = sf.openSession();
// HQL語句
String query = "select o from o "
+ "Order as o join o.products as p "
+ "where o.priceTotal > :priceTotalLower"
+ "and o.priceTotal< :priceTotalUpper";
Query q = sess.createQuery(query);
// 將兩個參數傳入HQL中
q.setDouble("priceTotalLower", Double.parseDouble(lower));
q.setDouble("priceTotalUpper", Double.parseDouble(upper));
List list = q.list();
Order o=(Order)list.iterator.next();
return o;
}
… …
}

下面的main函數將測試MyOrder類

public class MyOrder
{
… …
public static void main(String args[])
{
Order o=MyOrder().getOrder(“100”, “300”);
System.out.println(“id=”+ o.id);
… …
}
}

小結

上述的代碼演示了如何在Java中使用HQL,但HQL還有兩點需要注意一下:

1.HQL並不區分字母的大小寫,但在HQL中的Java類和屬性名必須和實際的類和屬性名一致。如SELECT和select之間可以互換,但Order和order卻代表不同的含義。

2.如果HQL中引用的類未被導入,在HQL中必須引用具體的包。如本例中,如果com.Order未被導入,在HQL中必須將Order寫成com.Order。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved