1. 程式人生 > >Hibernate(一)HQL查詢、原生sql查詢

Hibernate(一)HQL查詢、原生sql查詢

          Hibernate中支援三種查詢方式:HQL(Hibernate Query Language)原生sql查詢Criteria查詢HQL是一種面向物件的查詢語言,其中沒有表和欄位的概念,只有類、物件、屬性的概念;原生sql查詢就是我們程式設計師手動的寫sql語句並執行;Criteria查詢又稱為物件查詢,採用真正的面向物件的方式進行查詢,Criteria查詢將在後續篇章中進行單獨講解,本篇文章只講解HQL查詢和原生sql查詢。

        環境:
            本篇及後續文章都將使用Oracle資料庫、Oracle自帶的兩張資料表Dept和Emp以及Hibernate4為例進行講述

一、HQL查詢

1.HQL語句的組成
①from子句

最為簡單的查詢語句,比如:

from Dept

②select子句
主要用於選取物件的屬性(投影),如:

select deptNo from Dept
        詳細將在後續講解
③where子句
用於新增查詢條件,如:
from Dept where deptNo=2
④表示式
一般用在where子句中,如:
from Dept where lower(deptName)='sales'
⑤order by 子句
用於按照指定屬性進行排序,如:
from Emp order by hireDate asc
注意:

       a.from後面跟的

都不是表的名字,而是表對應的實體類的名字,必須完全一致;相應的,語句中的deptName、deptNo等都是 實體類屬性的名字,而不是表中列的名字
       b.可以為實體類起別名,如:from Dept d where d.deptNo=2
       c.select、from、where...等關鍵詞不區分大小寫,實體類和屬性名要完全一致

2.執行HQL語句
介紹瞭如何編寫HQL語句,下面來介紹下如何來執行。HQL的查詢是通過Hibernate的Query介面來實現的

//準備HQL語句
	String hql="from Dept";
	//使用createQuery()方法來建立Query介面實現類
	Query query=session.createQuery(hql);
這裡可以使用兩種方式進行查詢:
①使用list()方法
public static void main(String[] args) {
		Session session=HibernateUtil.currentSession();
		Transaction tx=session.beginTransaction();
		
		//準備HQL語句
		String hql="from Dept";
		//使用createQuery()方法來建立Query介面實現類
		Query query=session.createQuery(hql);
		List<Dept> list=query.list();
		for (Dept dept : list) {
			System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
		}
		
		tx.commit();
		HibernateUtil.closeSession();
	}
執行結果:
Hibernate: 
   select
             dept0_.DEPTNO as DEPTNO0_,
             dept0_.DNAME as DNAME0_,
             dept0_.LOC as LOC0_ 
   from
              MYDEPT dept0_
50vacant
60test2
10ACCOUNTING
20RESEARCH
30SALES
40OPERATIONS

②使用iterate()方法
public static void main(String[] args) {
		Session session=HibernateUtil.currentSession();
		Transaction tx=session.beginTransaction();
		
		//準備HQL語句
		String hql="from Dept";
		//使用createQuery()方法來建立Query介面實現類
		Query query=session.createQuery(hql);
		Iterator<Dept> list=query.iterate();
		Dept dept=null;
		while (list.hasNext()) {
			dept = list.next();
			System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
		}
		
		tx.commit();
		HibernateUtil.closeSession();
	}
執行結果:
Hibernate: 
   select
             dept0_.DEPTNO as col_0_0_ 
   from
             MYDEPT dept0_
Hibernate: 
   select
              dept0_.DEPTNO as DEPTNO0_0_,
              dept0_.DNAME as DNAME0_0_,
              dept0_.LOC as LOC0_0_ 
   from
              MYDEPT dept0_ 
   where
               dept0_.DEPTNO=?
10 ACCOUNTING
Hibernate: 
   select
            dept0_.DEPTNO as DEPTNO0_0_,
            dept0_.DNAME as DNAME0_0_,
            dept0_.LOC as LOC0_0_ 
   from
            MYDEPT dept0_ 
   where
            dept0_.DEPTNO=?
20 RESEARCH
.
.
.

          從生成的sql語句可以看出,使用list()方法是先查詢所有符合條件的記錄;而iterate()方法是首先查詢出所有符合條件的主鍵值(如:deptNo),然後在需要某一物件的其他

屬性值的時候再發送sql語句進行查詢;  

         這就是Hibernate的HQL查詢,關於where子句、order by等子句的使用就不做過多的解釋了(條件查詢的引數傳遞可以留作疑問)大同小異,童鞋們可以自己去多試試,多練練。

二、原生sql查詢

  Hibernate為HQL查詢生成了標準的sql查詢語句,適用於所有的資料庫平臺,所以HQL查詢可以跨平臺;但是有時候有可能需要使用底層資料庫的特性,來進行特殊的查詢,這時候原生sql查詢就派到了用場。
                  原生sql查詢同樣使用了Query介面,使用session.createSQLQuery()方法可以返回一個SQLQuery物件,SQLQuery介面繼承了Query介面在原生sql查詢中就要對應的寫表名和對應的列名了,而不是實體類和屬性名,下面看依照HQL查詢進行編碼:
public static void main(String[] args) {
		Session session=HibernateUtil.currentSession();
		Transaction tx=session.beginTransaction();
		
		//編寫sql語句
		String sql="select * from dept";
		//使用createSQLQuery()方法
		Query query=session.createSQLQuery(sql);
		List<Dept> list=query.list();
		for (Dept dept : list) {
			System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
		}
		
		tx.commit();
		HibernateUtil.closeSession();
	}
                執行結果: Hibernate: 
                 select
                              * 
                  from
                          dept
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.wzj.entity.Dept
at com.wzj.test.TestMain.main(TestMain.java:43)
誒,這時候發生了異常!控制檯輸出了型別轉換異常,這又是為什麼呢?看異常資訊,它說不能將Ljava.lang.Object這個型別轉換成Dept型別這個L代表陣列的意思,是說不能將物件陣列型別轉換成Dept型別。               是的,使用原生sql查詢查詢出來的是關係型資料,是Object[]型別,而不是像HQL查詢那樣直接封裝成了Dept物件,所以應該這樣寫:
//編寫sql語句
	String sql="select * from dept";
	//使用createSQLQuery()方法
	Query query=session.createSQLQuery(sql);
	List<Object[]> list=query.list();
	for (Object[] dept : list) {
		System.out.println(dept[0]+"\t"+dept[1]);
	}
這樣寫的話就會的得到查詢結果。 ①轉換查詢資料
        為了使查詢的資料直接封裝成Dept物件,Hibernate的SQLQuery介面提供了addEntity()方法來將關係資料轉換成物件型資料:
//編寫sql語句
	String sql="select * from dept";
	//注意addEntity()方法是SQLQuery介面特有的,使用query是呼叫不出來的
	Query query=session.createSQLQuery(sql).addEntity(Dept.class);
	List<Dept> list=query.list();
	for (Dept dept : list) {
		System.out.println(dept.getDeptNo()+"\t"+dept.getDeptName());
	}
②連線查詢
此外,SQLQuery介面還提供了addJoin()方法來進行連線查詢:
String sql="select e.*,d.* from EMP e join DEPT d on d.deptno=e.deptno";
	Query query=session.createSQLQuery(sql).addEntity("e",Emp.class)
					.addJoin("d","e.dept");
	//連線查詢返回Object陣列型別,第一個是元素是Emp物件,第二個是Dept物件
	List<Object[]> list=query.list();
	Emp emp=null;
	Dept dept=null;
	for (Object[] o : list) {
		emp=(Emp)o[0];
		dept=(Dept)o[1];
		System.out.println(emp.getEmpName()+"\t"+dept.getDeptName());
	}

執行結果:             Hibernate: 
                   select
                               e.*,
                               d.* 
                   from
                                EMP e 
                   join
                                DEPT d 
                   on d.deptno=e.deptno
CLARKACCOUNTING
KINGACCOUNTING
MILLERACCOUNTING
JONESRESEARCH
FORDRESEARCH
ADAMSRESEARCH
SMITHRESEARCH