初識hibernate——hql

hql基本介紹

HQL(HibernateQuery Language)查詢提供了豐富的和靈活的查詢特性,在涵蓋Criteria查詢的所有功能的前提下,提供了類似標準SQL語句的查詢方式,同時也提供了更加面向對象的封裝。因此Hibernate將HQL查詢方式立爲官方推薦的標準查詢方式,完整的HQL語句形式如下: Select/update/delete…… from …… where …… group by ……having …… order by …… asc/desc 其中的update/delete爲Hibernate3中所新添加的功能,可見HQL查詢非常類似於標準SQL查詢。由於HQL查詢在整個Hibernate實體操作體系中的核心地位,這一節我將專門圍繞HQL操作的具體技術細節進行講解。

 在hql中關鍵字不區分大小寫,通常小寫,類的名稱和屬性名稱必須區分大小寫

 HQL包括的各種查詢

 

 

1、簡單屬性查詢【重要】

    *單一屬性查詢,返會屬性結果集列表,元素類型和實體類中相應的類型一致

    *多個屬性查詢,多個屬性查詢返會對象數組,對象數組的長度取決於屬性的個數,對象數組中元素的類型取決於屬性在實體類中的類型

    *如果認爲返會數組不夠對象化,可以使用hql動態實例化Student對象

  

單一屬性查詢

//返回結果集屬性列表,元素類型和實體類中的屬性類型一致

Liststudents = session.createQuery("select name from Student").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Stringname = (String)iter.next();

System.out.println(name);

}

 

 

多個屬性查詢

//查詢多個屬性,返回對象數組集合

//數組元素的類型與查詢的屬性類型一致

//數組的長度與select中查詢的屬性個數一致

Liststudents = session.createQuery("select id, name fromStudent").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

 

多個屬性查詢,返回Student

//可以使用hql返回Student對象

//需要提供構造函數

Liststudents = session.createQuery("select new Student(id, name) fromStudent").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getId()+ ", " + student.getName());

}

 

 

使用別名

//可以使用別名

Liststudents = session.createQuery("select s.id, s.name from Students").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

 

//可以採用as命名別名

Liststudents = session.createQuery("select s.id, s.name from Student ass").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

 

 

2、實體對象查詢【重要】

    * N + 1問題,就是發出了N+1條sql語句

     1:首先發出查詢對象id列表的語句

     N:根據id到緩存中查詢,如果緩存中不存在與之匹配的數據,那麼會根據id發出相應的sql語句

   

    *list和iterate的區別?

     list:默認情況下list每次都會發出sql語句,list會將數據放到緩存中,而不利用緩存

     iterate:默認情況下iterate利用緩存,如果緩存中不存在會出現N+1問題

//返回Student對象的集合

//可以忽select關鍵字

Liststudents = session.createQuery("from Student").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}

 

/**

 * 採用list查詢實體對象會發出一條查詢語句,取得實體對象數據

 * 

 * Hibernate: select student0_.id as id0_,student0_.name as name0_, 

 * student0_.createTime as createTime0_,student0_.classesid as classesid0_ 

 * from t_student student0_

 */

Liststudents = session.createQuery("from Student").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}


 

3、條件查詢【重要】

    *可以採用拼字符串的方式傳遞參數

//可以拼串

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.name like '%0%'").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

    * 可以採用?來傳遞參數(索引從0開始)

//可以使用?方式傳遞參數

//索引從0開始,不同於jdbc從1開始

//值能使用單引號引起來

//Liststudents = session.createQuery("select s.id, s.name from Student s wheres.name like ?").list();

//                        Queryquery  = session.createQuery("selects.id, s.name from Student s where s.name like ?");

//                        query.setParameter(0,"%0%");

//                        Liststudents = query.list();

 

//方法鏈編程,建議採用此種方式

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.name like ?")

.setParameter(0,"%0%")

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

    * 可以採用:參數名 來傳遞參數

 

 

//可以採用:參數名 的方式傳遞參數

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.name like :myname")

.setParameter("myname",  "%0%")

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

 

    *如果傳遞多個參數,可以採用setParamterList方法

//採用?方式,查詢學號爲1,2,3,4,5的學生

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.id in(?, ?, ?, ?, ?)")

.setParameter(0,1)

.setParameter(1,2)

.setParameter(2,3)

.setParameter(3,4)

.setParameter(4,5)

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}


 

    *在hql中可以使用數據庫的函數,如:date_format 

 

//採用:參數名 方式,查詢學號爲1,2,3,4,5的學生

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.id in(:ids)")

.setParameterList("ids",new Object[]{1, 2, 3, 4, 5})

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}

//查詢2009-08的學生,可以調用mysql的日期格式化函數

Liststudents = session.createQuery("select s.id, s.name from Student s wheredate_format(s.createTime, '%Y-%m')=?")

.setParameter(0,  "2009-08")

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}

 

SimpleDateFormatsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

//查詢2009-08-01到2009-08-20的學生,可以調用mysql的日期格式化函數

Liststudents = session.createQuery("select s.id, s.name from Student s wheres.createTime between ? and ?")

.setParameter(0,sdf.parse("2009-08-01 00:00:00"))

.setParameter(1,sdf.parse("2009-08-20 23:59:59"))

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}

 

4、hibernate直接使用sql語句查詢

Liststudents = session.createSQLQuery("select * from t_student").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}

 

5、外置命名查詢

    * 在映射文件中使用<query>標籤來定義hql

    * 在程序中使用session.getNamedQuery()方法得到hql查詢串

   

    

<queryname="queryStudent">

<![CDATA[

selects from Student s where s.id <?

]]>

</query>

 

List students =session.getNamedQuery("queryStudent")

.setParameter(0,10)

.list();

for (Iteratoriter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}

 

 

6、查詢過濾器

    *在映射文件中定義過濾器參數

    *在類的映射中使用過濾器參數

    *在程序中必須顯示的啓用過濾器,並且爲過濾器參數賦值

<filter-defname="testFilter">

<filter-paramtype="integer" name="myid"/>

</filter-def>
session.enableFilter("testFilter")

.setParameter("myid",10);

Liststudents = session.createQuery("from Student").list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}

 

 

7、分頁查詢【重要】

    *setFirstResult(),從0開始

    *setMaxResults(),每頁顯示的記錄數

Liststudents = session.createQuery("from Student")

.setFirstResult(1)

.setMaxResults(2)

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}

 

 

8、對象導航查詢【重要】

 

Liststudents = session.createQuery("from Student s where s.classes.name like'%2%'")

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Studentstudent = (Student)iter.next();

System.out.println(student.getName());

}


 

9、連接查詢【重要】

    * 內連接

    * 外連接(左連接/右連接)left join     right join

Liststudents = session.createQuery("select c.name, s.name from Student s joins.classes c")

.list();

for(Iterator iter=students.iterator(); iter.hasNext();) {

Object[]obj = (Object[])iter.next();

System.out.println(obj[0]+ ", " + obj[1]);

}

 

10、統計查詢【重要】

Longcount = (Long)session.createQuery("select count(*) fromStudent").uniqueResult();


11、DML風格的操作(儘量少用,因爲和緩存不同步)        

@SuppressWarnings("unused")

//Studentstudent = (Student)session.load(Student.class, 1);

Studentstudent = (Student)session.get(Student.class, 1);

 

//數據庫表中更新了,但緩存不更新

//所以一般不建議使用,除非有必須,如遇到性能問題

session.createQuery("updateStudent s set s.name=? where s.id<?")

.setParameter(0,"王五")

.setParameter(1,5)

.executeUpdate();

 

//student= (Student)session.load(Student.class, 1);

student= (Student)session.get(Student.class, 1);

System.out.println("student.name="+ student.getName());


 總結:

HQL查詢跟我們之前學過的SQL有百分之八十的相似,所以,學起來不僅沒有抵觸反而更增加了學習的興趣,從而更好的去學習HQL,並且對SQL也有一定的惠顧,這也就是我們所學的N+1理論,同時我們從HQL的發展也可以看出,他並沒有獨闢蹊徑,重新編寫一種語言,而是更多地沿用SQL的使用習慣,讓使用的人更加方便,也其實也是我們編寫軟件的宗旨,並不是越奇特越好,而是能讓用戶能夠由衷的感覺到他不生澀,即達到了用戶的使用目的,也讓用戶能夠由衷的喜歡你的軟件

 

 

 

發佈了146 篇原創文章 · 獲贊 53 · 訪問量 89萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章