## 【含義】
hql,即Hibernate Query ?Language。它與我們熟知的sql很類似,它最大的特點就是對查詢進行了面向對象的封裝,下面會在具體例子中說明。
sql查詢的是數據庫中的表或字段,而hql是**面向對象**的,具有繼承、多態、關聯等特性,他針對的是對象。
## 【使用】
那么如何使用hql進行查詢呢?首先,我們需要宏觀看一下hql的幾種使用方式:**基本使用、外置命名和過濾器。**
基本使用即我們將hql語句寫在代碼中,執行操作。配置文件的方式是將我們所寫的hql語句轉移到配置文件中,這樣就很容易對其進行修改了。第三種過濾器,類似Struts中的Filter過濾器。它對查詢的內容進行過濾,在映射文件中定義過濾器,程序中啟用過濾器,并為過濾器參數賦值。

## 【基本使用】
我們先通過例子,了解下hql的基本使用,再介紹其實現原理。
~~~
/**
* 實體對象查詢,
*/
public void testquery(){
Session session=null;
try{
//獲得Hibernate Session
session=HibernateUtil.getSession();
//開啟事務
session.beginTransaction();
//以hql語句創建Query對象,Query調用list方法返回全部實例
List shelfList=session.createQuery("from Shelf").list();
//迭代顯示數據
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Shelf shelf=(Shelf)iter.next();
System.out.println(shelf.getLocation());
}
//提交事務
session.getTransaction().commit();
}catch(Exception e){
//發生異常,事務回滾
e.printStackTrace();
session.getTransaction().rollback();
}finally{
//關閉Session
HibernateUtil.closeSession(session);
}
}
/**
* 封裝類
*/
public class HibernateUtil {
private static SessionFactory factory;
/**
* 完成sessionFactory的初始化
*/
static{
try{
//讀取hibernate.cfg.xml配置文件
Configuration cfg=new Configuration().configure();
//建立sessionFactory,可訪問mysql
factory=cfg.buildSessionFactory();
}catch(Exception e){
e.printStackTrace();
}finally{
}
}
//獲得session
public static Session getSession(){
return factory.openSession();
}
//關閉session
public static void closeSession(Session session){
if(session!=null){
if(session.isOpen()){
session.close();
}
}
}
//返回sessionFactory
public static SessionFactory getSessionFactory(){
return factory;
}
}
~~~
Session——對象的增刪改查操作
Query,Criteria——執行數據庫查詢
SessionFactory——初始化Hibernate,創建Session對象。
Configuration——負責配置、啟動Hibernate,創建SessionFactory對象。

## 【外置命名】
外置命名和下面要說的過濾器都是些在配置文件中的,靈活性較好。
需求是,查詢Shelf中"code>1"的數據。我們需要在配置文件中,加入hql語句。
~~~
<hibernate-mapping >
<class name="com.hibernate.Shelf" table="t_shelf" >
<!-- 映射主鍵 -->
<id name="code">
<generator class="native"></generator>
</id>
</class>
<!--外置命名-->
<query name="queryShelf">
<![CDATA[
select s from Shelf s where s.code>?
]]>
</query>
</hibernate-mapping>
~~~
接下來,代碼中就不需要再寫hql語句了,但需要注意的是,要使用session的getNameQuery()方法,還要給hql中的問號占位符賦值,這里類似參數化查詢的東西,也很好理解。
~~~
<span style="white-space:pre"> </span>List shelfList=session.getNamedQuery("queryShelf").setParameter(0, 1).list();
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Shelf shelf=(Shelf)iter.next();
System.out.println(shelf.getLocation());
}
~~~
## 【過濾器】
過濾器的配置同樣也是在配置文件中,這里,我們需要命名過濾器名稱和參數名,以及哪個類使用過濾器
~~~
<hibernate-mapping >
<class name="com.hibernate.Shelf" table="t_shelf" >
<!-- 映射主鍵 -->
<id name="code">
<generator class="native"></generator>
</id>
<filter name="testFilter" condition="code < :myParam"></filter>
</class>
<!-- 過濾器 -->
<filter-def name="testFilter">
<filter-param name="myParam" type="integer"/>
</filter-def>
</hibernate-mapping>
~~~
? ? ?代碼中也和外置命名類似。
~~~
session.enableFilter("testFilter").setParameter("myParam", 2);//在session中都被啟用
List shelfList=session.createQuery("from Shelf").list();
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Book book=(Book)iter.next();
System.out.println(book.getName());
}
~~~
## 【小結】
在介紹基本使用方法時,主要是以理解hql的查詢原理,不能只停留在會用而已。
外置命名將hql語句抽離出來放到配置文件中,并給了他一個參數名,我們只需要在代碼中用這個參數名就可以了。這樣如果需求有不太大的變動時,我們就能輕松應對了。
過濾器類似Filter,也是在配置文件中,我們需要開啟過濾器,讓他幫我們把符合條件的數據過濾出來。但這種方式在面對復雜條件查詢的時候可能會不那么方便了。