SSH:Hibernate框架(Hibernate:HQL與QBC查詢方式詳解 )

首先來看一下,hibernate提供的幾種檢索方式:
1.導航對象圖檢索方式 :根據已經加載的對象,導航到其他對象。例如,對於已經加載的Customer對象,調用它的getOrders().iterator()方法就可以導航到所有關聯的Order對象,假如在關聯級別使用了延遲加載檢索策略,那麼首次執行此方法時,Hibernate會從數據庫中加載關聯的Order對象,否則就從緩存中取得Order對象。

2、OID檢索方式 :按照對象的OID來檢索對象。Session的get()和load()方法提供了這種功能。如果在應用程序中事先知道了OID,就可以使用這種檢索對象的方式。

3、HQL檢索方式 :Hibernate提供了Query接口,它是Hibernate提供的專門的HQL查詢接口,能夠執行各種複雜的HQL查詢語句。

4、QBC檢索方式 :使用QBC(Query By Criteria)API來檢索對象。這種API封裝了基於字符串形式的查詢語句,提供了更加面向對象的接口。
前兩種在前面我們都熟練的用過多次了,現在我們來看一下HQL檢索方式。HQL(Hibernate Query Language)是面向對象的查詢語言,它和SQL查詢語言有些相似。在Hibernate提供的各種檢索方式中,HQL是使用最廣的一種檢索方式。它具有以下功能:

–在查詢語句中設定各種查詢條件
–支持投影查詢,即僅檢索出對象的部分屬性
–支持分頁查詢
–支持連接查詢
–支持分組查詢,允許使用having和group by關鍵字
–提供內置聚集函數,如sum()、min()和max()
–支持子查詢,即嵌入式查詢
–支持動態綁定參數

下面我們通過一個實例來看一下HQL檢索的步驟:
[java] view plaincopyprint?
//創建一個Query對象
Query query=session.createQuery(“from Customer as c where ”
+” c.name=:customerName ”
+”and c.age=:customerAge”);
//動態綁定參數
query.setString(“customerName”,”Tom”);
query.setInteger(“customerAge”,21);
//執行查詢語句,返回查詢結果
List result= query.list();

從上面這個實例我們可以看出:
(1)通過Session的createQuery()方法創建一個Query對象,它包含一個HQL查詢語句。HQL查詢語句可以包含命名參數,如“customerName”和“customerAge”都是命名參數。
(2)動態綁定參數。Query接口提供了給各種類型的命名參數賦值的方法,例如setString()方法用於爲字符串類型的customerName命名參數賦值。
(3)調用Query的list()方法執行查詢語句。該方法返回List類型的查詢結果,在List集合中存放了符合查詢條件的持久化對象。
Query中還提供了良好的方法連編程方式,查看hibernate的API我們可以發現,query類提供的set方法的返回值還是query對象,這樣可以使代碼更爲簡介:例如。
[java] view plaincopyprint?
List result=session.createQuery(“……”) .setString(“customerName”,”Tom”)
.setInteger(“customerAge”,21) .list();

QBC
採用HQL檢索方式時,在應用程序中需要定義基於字符串形式的HQL查詢語句。 QBC API 提供了檢索對象的另一種方式,它主要由Criteria接口、Criterion接口和Expression類組成,它支持在運行時動態生成查詢語句。
QBC檢索步驟:

1)調用Session的createCriteria()方法創建一個Criteria對象。
2)設定查詢條件。Expression類提供了一系列用於設定查詢條件的靜態方法,這些靜態方法都返回Criterion實例,每個Criterion實例代表一個查詢條件。Criteria的add()方法用於加入查詢條件。
3)調用Criteria的list()方法執行查詢語句。該方法返回List類型的查詢結果,在List集合中存放了符合查詢條件的持久化對象。下面還是通過一個實例來看一下QBC查詢的具體步驟:
[java] view plaincopyprint?
//創建一個Criteria對象
Criteria criteria=session.createCriteria(Customer.class);
//設定查詢條件,然後把查詢條件加入到Criteria中
Criterion criterion1= Expression.like(“name”, “T%”) ;
Criterion criterion2= Expression.eq(“age”, new Integer(21)) ;
criteria=criteria.add(criterion1);
criteria=criteria.add(criterion2);
//執行查詢語句,返回查詢結果
List result=criteria.list();

對於以上程序代碼,當運行Criteria的list()方法時,Hibernate執行的SQL查詢語句爲:
select * from CUSTOMERS where NAME like ‘T%’ and AGE=21;
注:Expression;類是org.hibernate.criterion.Restrictions的子類,所以也可以換成該類。Criteria也是採用的方法連的編程風格,因爲add方法返回值也是Criteria,就像下面這段代碼:
[java] view plaincopyprint?
List result=session.createCriteria(Customer.class).add(Expression.like(“name”, “T%”) .add(Expression.eq(“age”, newInteger(21)) .list();

Query和Criteria接口都提供了用於分頁顯示查詢結果的方法:
–setFirstResult(int firstResult):設定從哪一個對象開始檢索,參數firstResult表示這個對象在查詢結果中的索引位置,索引位置的起始值爲0。默認情況下,Query和Criteria接口從查詢結果中的第一個對象,也就是索引位置爲0的對象開始檢索。
–setMaxResult(int maxResults):設定一次最多檢索出的對象數目。默認情況下,Query和Criteria接口檢索出查詢結果中所有的對象。
分頁查詢:
採用HQL檢索方式 :
[java] view plaincopyprint?
Query query = session.createQuery(“from
Customer c
order by c.name asc”);
query.setFirstResult(0);
query.setMaxResults(10);
List result = query.list();

採用QBC檢索方式
[java] view plaincopyprint?
Criteria criteria = session.createCriteria(
Customer.class);
criteria.addOrder( //criteria裏面提供添加排序方式的方法
Order.asc(“name”) );
criteria.setFirstResult(0);
criteria.setMaxResults(10);
List result = criteria.list()
上面我們大體瞭解了hql語句和QBC兩種查詢方式,具體的用法我們來看一下,首先看一下HQL.
我們平時查詢的時候,HQL語句總是”from 類名”,這樣查詢,這是我們想要查詢出對應對象的所有屬性。當我們只是想查詢實體類的其中的幾個字段,而不是整個實體類的對象時,我們就需要把前面省略的hql語句加上了。例如HQL語句:select s.name,s.age from student s ,他代表只是查詢student表中的name和age屬性,其他的不要。這時調用query。List()方法時返回的不是一個個對象了,因爲我們查詢的只是對象的一部分屬性。那查詢到的list集合裏是什麼東東呢。其實list對象中裏面每一個元素是一個object對象的數組,每一個數組包含查詢對象的幾個字段。這些數據只是一些遊離的數據。我們想獲得的字段數據可以用下面方式去遍歷。
代碼如下:

以上情況還可以用另一種方式來解決但這種方式方式成功執行的前提是,在student實體類裏面構造了包含name和age兩個屬性的構造方法。
[java] view plaincopyprint?
Query query = session.createQuery(“select new Student(s.name, s.age) from Student s”);
List list = query.list();
for(int i = 0; i < list.size(); i++)
{Student student = (Student)list.get(i) System.out.println(student.getName() + “, ” + student.getAge());
System.out.println(student.getCardId());//此處返回空,數據庫沒有查該字段
}

    通過上面HQL語句我們可以看出,這時查詢出來的就是一個個student對象了,而不是一個個遊離的數據了,這裏一定要注意HQL語句的寫法。這種寫法在sql語句中肯定是不支持的。
    HQL語句進行內連接查詢:from Team t  join t.student;這條內連接語句意思爲讓team表和student表進行內連接查詢。很多同學回想沒有on語句,查詢條件是什麼呢?這是由於hbm文件已經註明了表之間的字段連接關係,所以他會自動去on連接。下面看一下自動生成的sql語句大家就沒白了。

Hibernate自動生成的查詢語句爲:

      Hibernate配置給我們提供了一個格式化sql語句的配置,配置sql_format的屬性爲true,就會向上面那樣,得到格式化的sql語句。
      在內連接查詢結果中,剛開始我有這麼一個疑問,連接查詢得到的結果集是兩個表中的並集集合,那得到的對象到底是哪一個呢?不是student。也是不是team。原來,hibernate早就給我們準備了這個東西。當我們調用list方法獲得結果的集合時,得到的集合實際上是object數組的集合。這個數組裏面一般有兩個對象,像上面那條hql語句就是得到的student對象和team對象數組的集合,下面我們就看一下具體的代碼實現:

[java] view plaincopyprint?
Query query = session.createQuery(“from Team t join t.students”);
List list = query.list();
for(int i = 0; i < list.size(); i++)
{
Object[] obj = (Object[]) list.get(i);
Team team = (Team)obj[0];
Student student = (Student)obj[1];
System.out.println(team.getTeamName());
System.out.println(student.getName());
}

    內連接中還深藏着一個不爲人知的祕密,當我們把延遲加載設爲true,也就是讓他延遲加載對應對象信息時,我們在session關閉之後去遍歷list集合,這時你會發現一樣的加載出來對應的student的信息,這時因爲內連接查詢把配置文件中的延遲加載信息給覆蓋掉了。在session關閉之前就把對應的對象信息給加載出來了。

hql中實體參數設置
下面我們在來看一下hibernate用hql中實體參數設置,所謂實體參數設置就是在利用HQL語句執行操作時,對HQL語句中設置參數,以前我們接觸到的都是一些基本數據類型的參數設置,hibernate中都提供了相應的set方法,下面我們來看一下下面一個hql查詢:
[java] view plaincopyprint?
Team team=session.get(Team.class,1);
Query query = session.createQuery(“from student s where s.team=:team and s.age>20”);

   在這個地方,我們查詢的條件爲學生對應的team對象與剛查詢出來的對象相等。在hibernateAPI中提供了兩種方式設置這個地方的參數,下面我們一一來看一下:

1.第一種:
query.setParameter(“team”,team,Hibernate.entity(Team.class));這種方式需要三個參數,第一個參數是指定設定的參數,這裏設置的是上面hql語句中的team參數,第二個參數是設置參數的值,第三個參數是一個Type類型的數據,hibernate中提供了一個Hibernate類,他裏面包含了大量的靜態工具方法,其中就有獲得Type對象的方法entity。
2.第二種:
query.setEntity(“team”,team),這個方法比較簡單,並且比較實用,我們在大多數的時候都使用這一個,他和設置基本數據類型的set方法比較相識。直接設置參數名和參數值就OK了。
值得注意的是,這裏的hql語句這樣比較兩個對象是否相等,其實在hibernate底層會轉換成對應的外鍵關聯。
過濾:
hibernateAPI提供了一個起到過濾器作用的方法,這個方法就是createFiter(object collection,string s)方法,他有兩個參數,第一個參數是指所要過濾的對象,也就是集合對象,第二個參數指的是過濾語句,其實就是hql語句的一部分:例如下面這段代碼:
[java] view plaincopyprint?
Query query = session.createFilter(team.getStudents(), “where age > 20”);
List list = query.list();

QBC:作爲真正的面向對象對數據庫進行操作的一種方式,其內部提供了大量的API對數據庫操作和條件,下面我們根據具體示例來看一下其API的的用法:
[java] view plaincopyprint?
//增加年齡限制12-30歲
Criteria criteria = session.createCriteria(Student.class).add(
Restrictions.between(“age”, new Integer(12), new Integer(30)));
//增加name條件限制,名字以t開頭的
Criteria criteria = session.createCriteria(Student.class).add(
Restrictions.like(“name”, “t%”));
//增加範圍限制,名字必須是”jerry”, “spark”, “tom”中的一個
String[] names = { “jerry”, “spark”, “tom” };
Criteria criteria = session.createCriteria(Student.class).add(
Restrictions.in(“name”, names));
//對查詢到的數據進行排序,以age升序,以cardid降序
Criteria criteria = session.createCriteria(Student.class).addOrder(
Order.asc(“age”)).addOrder(Order.desc(“cardId”));
//執行數據查詢
List list = criteria.list();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章