序言
之前對hibernate中的查詢總是搞混淆,不明白裡面具體有哪些東西。就是因為缺少總結。在看這篇文章之前,你應該知道的是資料庫的一些查詢操作,多表查詢等,如果不明白,可以先去看一下 MySQL資料表查詢操作詳解 ,以至於看這篇文章不用那麼吃力。
--WH
一、hibernate中的5種檢索方式
1.1、導航物件圖檢索方式
根據已經載入的物件導航到其他物件
例如:在前面的各種對映關係中,實體類包含對其他類物件的引用。
Dept d = (Dept) session.get(Dept.class,2);
d.getStaffSet().size(); //d物件關聯Staff集合,hibernate會自動檢索Staff資料。如何檢索的,看下面圖中傳送的sql語句。
1.2、OID檢索方式
按照物件的OID來檢索物件
例如:session.get()/session.load()
這個大家度很熟悉了,就不用在這裡過多的闡述了。
1.3、HQL檢索方式
HQL:Hibernate Query Language ,是物件導向的查詢語言,它和SQL查詢語言有些相似,在Hibernate提供的各種檢索方式中,HQL是使用的最廣的一種檢索方式,
注意:HQL操作的全是POJO類中的屬性,而不是運算元據庫表中的欄位。
1.3.1、在查詢語句中設定各種查詢條件
1.3.2、支援投影查詢,即僅檢索出物件的部分屬性
1.3.3、支援分頁查詢
1.3.4、支援連線查詢
1.3.5、支援分組查詢,允許使用HAVING 和 GROUP BY 關鍵字
1.3.6、提供內建聚集函式,如SUM(),MIN(),MAX()等
1.3.7、能夠呼叫使用者定義的SQL函式或標準的SQL函式
1.3.8、支援子查詢
1.3.9、支援動態繫結引數
使用HQL檢索步驟:
1>獲得session
2>編寫HQL
3>通過session.createQuery(HQL)建立Query物件
4>為Query物件設定條件引數(如果HQL中需要填充引數的話)
5>執行查詢
list():返回一個集合列表,有可能集合中裝的是陣列,有可能是POJO物件。
uniqueResult():返回一個查詢結果,在已知查詢結果只有一個或者0個時,使用是沒有問題的,如果返回結果有多個,那麼就會報異常
實驗
建立環境,使用Dept和Staff的雙向一對多關係,其中具體的程式碼就不在列舉出來了。重點不在這裡。原始記錄Staff中有9條記錄,都指向了Dept中id為2的部門。
1.3.1、在查詢語句中設定各種查詢條件
1.3.1.1、查詢全部記錄,沒有查詢條件
1 //沒有條件的hql,也就是查詢全部記錄。 2 String hql = "from Staff"; 3 Query hqlQuery = session.createQuery(hql); 4 List<Staff> list = hqlQuery.list(); 5 for(Staff staff : list){ 6 System.out.println(staff.toString()); 7 }
結果
1.3.1.2、條件查詢,查詢出id=3的staff資訊
1 String hql = "from Staff where id = 3"; 2 Query hqlQuery = session.createQuery(hql); 3 //方式一 4 // List<Staff> list = hqlQuery.list(); 5 // for(Staff staff : list){ 6 // System.out.println(staff.toString()); 7 // } 8 //方式二,已知只有一條資料,使用uniqueResult 9 Staff staff = (Staff) hqlQuery.uniqueResult(); 10 System.out.println(staff.toString()); 11 12 //結果 13 Hibernate: 14 select 15 staff0_.id as id1_, 16 staff0_.name as name1_, 17 staff0_.deptId as deptId1_ 18 from 19 staff staff0_ 20 where 21 staff0_.id=3 22 //因為是立即檢索,所有有了這條語句,這裡不做解釋, 23 Hibernate: 24 select 25 dept0_.id as id0_0_, 26 dept0_.name as name0_0_ 27 from 28 dept dept0_ 29 where 30 dept0_.id=? 31 //查詢到了響應結果 32 Staff [id=3, name=qqq2, dept=oneToMany.Dept@cc0e21a]
1.3.2、支援投影查詢,即僅檢索出物件的部分屬性
也就是不需要將表中所有的欄位度查詢出來,只查詢出物件的部分屬性,這就是投影查詢
1.3.2.1、什麼度不使用,直接查詢,得到的結果就是將查到的屬性全放到list集合中。這隻使用於檢索物件的一個屬性,如果多個屬性,就得需要用別的方式進行封裝
1 String hql = "select name from Staff"; 2 Query hqlQuery = session.createQuery(hql); 3 List list = hqlQuery.list(); //集合中存放的是String,也就是name屬性值。 4 System.out.println(list); 5 6 //結果 7 Hibernate: 8 select 9 staff0_.name as col_0_0_ 10 from 11 staff staff0_ 12 [qqq1, qqq2, qqq3, qqq4, qqq5, qqq6, qqq7, qqq8, qqq9]
1.3.2.2、使用new List()或者new Map()或new Staff()將返回的值給封裝起來
使用new Staff()
1 //使用new Staff(id,name)的前提是Staff的實體類中id和name這個構造器。反則報錯 2 String hql = "select new Staff(id,name) from Staff"; 3 Query hqlQuery = session.createQuery(hql); 4 List<Staff> list = hqlQuery.list(); //集合中存放的是Staff陣列。。 5 System.out.println(list); 6 //結果 7 Hibernate: 8 select 9 staff0_.id as col_0_0_, 10 staff0_.name as col_1_0_ 11 from 12 staff staff0_ 13 [Staff [id=2, name=qqq1, dept=null], Staff [id=3, name=qqq2, dept=null], Staff [id=4, name=qqq3, dept=null], Staff [id=5, name=qqq4, dept=null], 14 Staff [id=6, name=qqq5, dept=null], Staff [id=7, name=qqq6, dept=null], Staff [id=8, name=qqq7, dept=null], Staff [id=9, name=qqq8, dept=null], 15 Staff [id=10, name=qqq9, dept=null]]
使用new List()
1 //將查詢到的結果存放在list集合中,形式如 List[陣列1,陣列2...] 陣列1[id,name] 2 String hql = "select new List(id,name) from Staff"; 3 Query hqlQuery = session.createQuery(hql); 4 List list = hqlQuery.list(); //集合中存放的是id,name陣列。。 5 System.out.println(list); 6 7 //結果 8 Hibernate: 9 select 10 staff0_.id as col_0_0_, 11 staff0_.name as col_1_0_ 12 from 13 staff staff0_ 14 [[2, qqq1], [3, qqq2], [4, qqq3], [5, qqq4], [6, qqq5], 15 [7, qqq6], [8, qqq7], [9, qqq8], [10, qqq9]]
使用new Map()
//將查詢到的結果用map封裝,然後放到list集合中, String hql = "select new Map(id,name) from Staff"; Query hqlQuery = session.createQuery(hql); List list = hqlQuery.list(); //集合中存放的是id,name陣列。。 System.out.println(list); //結果 Hibernate: select staff0_.id as col_0_0_, staff0_.name as col_1_0_ from staff staff0_ [{1=qqq1, 0=2}, {1=qqq2, 0=3}, {1=qqq3, 0=4}, {1=qqq4, 0=5}, {1=qqq5, 0=6}, {1=qqq6, 0=7}, {1=qqq7, 0=8}, {1=qqq8, 0=9}, {1=qqq9, 0=10}]
1.3.3、支援分頁查詢
使用setFirst()和setMaxResult()分別設定起始索引和拿去資料的總數。跟limit m,n 是一樣的
String hql = "from Staff"; Query hqlQuery = session.createQuery(hql); //從資料庫表中取出第三條到第六條記錄來。相當於MySQL的limit 2,3; hqlQuery.setFirstResult(2); hqlQuery.setMaxResults(3); List<Staff> list = hqlQuery.list(); //集合中存放的是id,name陣列。。 for(Staff staff : list){ System.out.println(staff.toString()); } //結果 Hibernate: select staff0_.id as id1_, staff0_.name as name1_, staff0_.deptId as deptId1_ from staff staff0_ limit ?, ? Hibernate: select dept0_.id as id0_0_, dept0_.name as name0_0_ from dept dept0_ where dept0_.id=? //由於資料庫表中沒有id=1的資料,所以拿到的記錄是從id=4開始。也就是從第三條到第六條 Staff [id=4, name=qqq3, dept=oneToMany.Dept@2bf11e9f] Staff [id=5, name=qqq4, dept=oneToMany.Dept@2bf11e9f] Staff [id=6, name=qqq5, dept=oneToMany.Dept@2bf11e9f]
1.3.4、支援連線查詢
支援7種連線寫法。
1.3.4.1、內連線 inner join 可以省略inner,直接join
1 //注意,hql操作的是POJO,而不是表中欄位,所以s.dept這裡不能寫成Dept或者dept, 2 //不用寫ON後面的連線條件,因為hibernate對映檔案我們已經全部寫好了。 3 String hql = "from Dept d inner join d.staffSet"; 4 Query hqlQuery = session.createQuery(hql); 5 //這裡的泛型不能是Staff了。結合了兩張表,集合中存放的是Object[],陣列中存放的是Staff和Dept實體 6 List<Object[]> list = hqlQuery.list(); //集合中存放的是id,name陣列。。 7 Object[] o = list.get(0); 8 System.out.println(o); 9 //注意:其中Dept和Staff中都沒有對方實體的引用。因為這個是左外連線,生成了新的表。 10 System.out.println(((Dept)o[0]).getName());//獲得Dept實體的name 11 System.out.println(((Staff)o[1]).getName());//或者Staff的name 12 13 //結果 14 //左外連線的語句,並且為我們加上了ON之後的語句 15 Hibernate: 16 select 17 dept0_.id as id0_0_, 18 staffset1_.id as id1_1_, 19 dept0_.name as name0_0_, 20 staffset1_.name as name1_1_, 21 staffset1_.deptId as deptId1_1_ 22 from 23 dept dept0_ 24 inner join 25 staff staffset1_ 26 on dept0_.id=staffset1_.deptId 27 //這個是list中第一個Object[] 不用看他的格式,只要知道他有代表著Dept和Staff實體 28 [Ljava.lang.Object;@44eef74f 29 1部門 30 qqq1
1.3.4.2、迫切內連線 inner join fetch
內連線返回的list中是Object[],而迫切內連線返回的list中是POJO類物件
1 //注意,hql操作的是POJO,而不是表中欄位,所以s.dept這裡不能寫成Dept或者dept, 2 //不用寫ON後面的連線條件,因為hibernate對映檔案我們已經全部寫好了。 3 String hql = "from Dept d inner join fetch d.staffSet"; 4 Query hqlQuery = session.createQuery(hql); 5 //使用的是迫切內連線,其list中放的就是Dept物件了,注意並沒有包含staffSet。放的是from後面跟的POJO,如果是Staff。那麼這裡就放的Staff。 6 //所以自己重寫了toString方法的人這裡會報錯, 7 List list = hqlQuery.list(); //集合中存放的是Dept。 8 System.out.println(list); 9 10 //結果 11 Hibernate: 12 select 13 dept0_.id as id0_0_, 14 staffset1_.id as id1_1_, 15 dept0_.name as name0_0_, 16 staffset1_.name as name1_1_, 17 staffset1_.deptId as deptId1_1_, 18 staffset1_.deptId as deptId0_0__, 19 staffset1_.id as id0__ 20 from 21 dept dept0_ 22 inner join 23 staff staffset1_ 24 on dept0_.id=staffset1_.deptId 25 //返回那麼多相同的原因是內連線,Staff中有9條記錄,則部門這邊也會顯示9條,所以這裡重複了9次。可以是用DISTINCT關鍵字去除重複的記錄 26 [Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門], Dept [id=2, name=1部門]]
要想得到不重複的記錄,那麼就將hql改為"select distinct d from Dept d inner join fetch d.staffSet";
1.3.4.3、隱式內連線 不寫任何關鍵字,完成表連線
其實就是通過where連線兩張表。很簡單。
1 //隱式內連線,其實就是最普通的通過where來連線兩張表,如何看了MySQL的表查詢操作, 2 //這個應該很簡單,但是這裡只能通過多方找一方,因為一方存放的是集合,就不能向下面這樣賦值 3 String hql = "from Staff s where s.dept.name = ?"; 4 Query hqlQuery = session.createQuery(hql); 5 hqlQuery.setParameter(0, "1部門"); 6 7 List list = hqlQuery.list(); //集合中存放的是Dept。 8 System.out.println(list); 9 //結果 10 Hibernate: 11 select 12 staff0_.id as id1_, 13 staff0_.name as name1_, 14 staff0_.deptId as deptId1_ 15 from 16 staff staff0_ cross 17 join 18 dept dept1_ 19 where 20 staff0_.deptId=dept1_.id 21 and dept1_.name=? 22 [Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]
1.3.4.4、左外連線,left outer join,可以省略outer,直接left join
1 //左外連線,自己腦袋裡想一下在左外連線的時候,表會是什麼樣子。通過前面看到的內連線 2 //和迫切內連線就應該知道這裡左外連線list中存放的是什麼,就是Object[] 3 String hql = "from Staff s left outer join s.dept"; 4 Query hqlQuery = session.createQuery(hql); 5 6 List<Object[]> list = hqlQuery.list(); 7 Object[] object = list.get(0); 8 System.out.println(((Staff)object[0]).getName()); 9 System.out.println(((Dept)object[1]).getName()); 10 11 //結果 12 Hibernate: 13 select 14 staff0_.id as id1_0_, 15 dept1_.id as id0_1_, 16 staff0_.name as name1_0_, 17 staff0_.deptId as deptId1_0_, 18 dept1_.name as name0_1_ 19 from 20 staff staff0_ 21 left outer join 22 dept dept1_ 23 on staff0_.deptId=dept1_.id 24 qqq1 25 1部門
1.3.4.5、迫切左外連線, left outer join fetch
一樣的區別,就是list中存放的是POJO物件了
1 //迫切左外連線,就是list中存放的是POJO物件。在這裡存放的是Staff。 2 String hql = "from Staff s left outer join fetch s.dept"; 3 Query hqlQuery = session.createQuery(hql); 4 5 List list = hqlQuery.list(); 6 System.out.println(list); 7 8 //結果 9 Hibernate: 10 select 11 staff0_.id as id1_0_, 12 dept1_.id as id0_1_, 13 staff0_.name as name1_0_, 14 staff0_.deptId as deptId1_0_, 15 dept1_.name as name0_1_ 16 from 17 staff staff0_ 18 left outer join 19 dept dept1_ 20 on staff0_.deptId=dept1_.id 21 [Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], 22 Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]
1.3.4.6、右外連線:right outer join
知道左外連線,右外連線也就會了。
1 //右外連線,就是list中存放的是Object[] 2 String hql = "from Staff s right outer join s.dept"; 3 Query hqlQuery = session.createQuery(hql); 4 5 List<Object[]> list = hqlQuery.list(); 6 System.out.println(list); 7 8 //結果 9 Hibernate: 10 select 11 staff0_.id as id1_0_, 12 dept1_.id as id0_1_, 13 staff0_.name as name1_0_, 14 staff0_.deptId as deptId1_0_, 15 dept1_.name as name0_1_ 16 from 17 staff staff0_ 18 right outer join 19 dept dept1_ 20 on staff0_.deptId=dept1_.id 21 [[Ljava.lang.Object;@11e04129, [Ljava.lang.Object;@19d5f3ea, [Ljava.lang.Object;@2d8094e6, [Ljava.lang.Object;@54af9f60, [Ljava.lang.Object;@5608830f, [Ljava.lang.Object;@48d479e9, [Ljava.lang.Object;@758fd559, [Ljava.lang.Object;@3600025b, [Ljava.lang.Object;@3a9ac00f]
1.3.4.7、交叉連線,會產生笛卡爾積。
什麼是笛卡爾積?將兩張表連線起來,比如一張表中有3條記錄,另一張表中也有3條記錄,那麼連線之後,就會出現9條資料,其中就有一些重複的資料,拿例項說話,班級和學生,有三個學生A,B,C,有兩個班級E,F,連線起來後,就會出現笛卡爾積,6條資料,其中會出現這樣的資料,A,E 、A,F、B,E、B,F、C,E、C,F, A,B,C就重複出現了,即在E班級,又在F班級,這樣就不合理。這就是所說的笛卡爾積。
由於dept中就一條記錄,無法展示出笛卡爾積,所以手動增加一條dept的記錄。然後在進行交叉連線。就會出現笛卡爾積,
1 //直接將兩張表簡單相連,出現笛卡爾積,因為從結果中可以看到,list集合中有18個陣列,說明有18條記錄 2 String hql = "from Staff,Dept"; 3 Query hqlQuery = session.createQuery(hql); 4 5 List list = hqlQuery.list(); 6 System.out.println(list); 7 8 //結果 9 Hibernate: 10 select 11 staff0_.id as id1_0_, 12 dept1_.id as id0_1_, 13 staff0_.name as name1_0_, 14 staff0_.deptId as deptId1_0_, 15 dept1_.name as name0_1_ 16 from 17 staff staff0_ cross 18 join 19 dept dept1_ 20 //18個陣列 21 [[Ljava.lang.Object;@42064d82, [Ljava.lang.Object;@2bcab3ab, [Ljava.lang.Object;@8d9b603, [Ljava.lang.Object;@d3c837f, [Ljava.lang.Object;@7fdd0da2, [Ljava.lang.Object;@9aa4843, [Ljava.lang.Object;@a6e2baa, [Ljava.lang.Object;@46f4ab3f, [Ljava.lang.Object;@6916d97d, [Ljava.lang.Object;@5b20d371, [Ljava.lang.Object;@4819ce74, [Ljava.lang.Object;@164146a7, [Ljava.lang.Object;@1785895b, [Ljava.lang.Object;@3ffcc16d, [Ljava.lang.Object;@6afefbec, [Ljava.lang.Object;@a4d79d5, [Ljava.lang.Object;@6479943b, [Ljava.lang.Object;@69f2e105]
注意:上面的連線中很多是使用一個引用就代表了相對應的表,比如" from Dept d inner join d.staffSet " d.staffSet就好像代表了Staff的這張表,實際上就是代表了Staff這張表,這樣理解,from Dept 就從Dept表中找出了所有記錄,就打比方,找到了Dept表中的2部門,在2部門中有多少staff呢,可以全部找出來,在我們所說的環境下,正好就staff就全部在該部門中,那麼就找到了Staff表中的所有staff,也就是相當於是Staff這張表了,就算2部門沒有包括所有的staff,那麼還有其他部門,肯定包括了剩下的staff,也就是說,不管怎麼樣,度能把staff全部找到,所以d.staffSet就相當於Staff表了。以此類推,其他hql語句中的這裡也是這樣理解的。
1.3.5、支援分組查詢,允許使用HAVING 和 GROUP BY 關鍵字
1 //s.dept.id 就相當於操作Staff表中的deptId。看傳送的sql語句就能知道。 2 //原因是Staff這個類中並沒有deptId表欄位屬性,但是有dept的引用變數,其dept的id 3 //也就是Staff中的deptId值,只是中間轉換了一步,也不是很難理解。 4 String hql = "from Staff s group by s.dept.id"; 5 Query hqlQuery = session.createQuery(hql); 6 List list = hqlQuery.list(); 7 System.out.println(list); 8 9 //結果 10 Hibernate: 11 select 12 staff0_.id as id1_, 13 staff0_.name as name1_, 14 staff0_.deptId as deptId1_ 15 from 16 staff staff0_ 17 group by 18 staff0_.deptId 19 //分組後顯示的就是第一個值。由於資料問題,9個staff度是在一個部門,所以通過部門分組,就只能得到一個分組。 20 [Staff [id=2, name=qqq1]]
1.3.6、提供內建聚集函式,如SUM(),MIN(),MAX()等
這個例子中不好使用這幾個函式。。。所以這裡不演示了,很簡單。hql和sql差不太多。
1.3.7、能夠呼叫使用者定義的SQL函式或標準的SQL函式
這個跟上面的一樣,SQL中函式有很多。也就是說hql能夠使用sql中的函式
1.3.8、支援子查詢
1 //子查詢操作,實際意義:Staff表中的staff所在的部門編號,跟Dept中所有的部門編號有對應的,就將其staff取出。 2 String hql = "from Staff s where s.dept.id IN (select id from Dept)"; 3 Query hqlQuery = session.createQuery(hql); 4 List list = hqlQuery.list(); 5 System.out.println(list); 6 //結果 7 Hibernate: 8 select 9 staff0_.id as id1_, 10 staff0_.name as name1_, 11 staff0_.deptId as deptId1_ 12 from 13 staff staff0_ 14 where 15 staff0_.deptId in ( 16 select 17 dept1_.id 18 from 19 dept dept1_ 20 ) 21 [Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]
1.3.9、條件查詢,給hql中動態設定引數的兩種方式
方式一:from Staff where id = ? 使用?代替所需要填入的值,在下面設定值時則從0開始算起,第一個?是處於0的位置,如果有兩個?號,則使用0,1索引號來插入值。
1 String hql = "from Staff where id = ?"; 2 Query hqlQuery = session.createQuery(hql); 3 4 hqlQuery.setParameter(0, 4); 5 6 Staff staff = (Staff) hqlQuery.uniqueResult(); 7 System.out.println(staff.toString()); 8 9 //結果 10 Hibernate: 11 select 12 staff0_.id as id1_, 13 staff0_.name as name1_, 14 staff0_.deptId as deptId1_ 15 from 16 staff staff0_ 17 where 18 staff0_.id=? 19 Hibernate: 20 select 21 dept0_.id as id0_0_, 22 dept0_.name as name0_0_ 23 from 24 dept dept0_ 25 where 26 dept0_.id=? 27 Staff [id=4, name=qqq3, dept=oneToMany.Dept@f1cb8ac]
方式二:from Staff where id = :id 使用":id"這個名字來表示插入值的名稱,在下面則不用索引號來確定插入值的位置,直接是使用這個別稱
1 String hql = "from Staff where id = :id"; 2 Query hqlQuery = session.createQuery(hql); 3 4 hqlQuery.setParameter("id", 4); 5 6 Staff staff = (Staff) hqlQuery.uniqueResult(); 7 System.out.println(staff.toString()); 8 9 //結果 10 Hibernate: 11 select 12 staff0_.id as id1_, 13 staff0_.name as name1_, 14 staff0_.deptId as deptId1_ 15 from 16 staff staff0_ 17 where 18 staff0_.id=? 19 Hibernate: 20 select 21 dept0_.id as id0_0_, 22 dept0_.name as name0_0_ 23 from 24 dept dept0_ 25 where 26 dept0_.id=? 27 Staff [id=4, name=qqq3, dept=oneToMany.Dept@1539b7a6]
注意,在位置上不僅僅可以插入值,還可以插入一個物件。例如
1 String hql = "from Staff s where s.dept = ?"; 2 Query hqlQuery = session.createQuery(hql); 3 Dept dept = (Dept)session.get(Dept.class, 2); 4 hqlQuery.setEntity(0, dept); //給相應位置新增一個dept物件 5 List list = hqlQuery.list(); 6 System.out.println(list); 7 8 //結果 9 //這個是查詢dept傳送的sql語句 10 Hibernate: 11 select 12 dept0_.id as id0_0_, 13 dept0_.name as name0_0_ 14 from 15 dept dept0_ 16 where 17 dept0_.id=? 18 //這個是我們寫的hql傳送的sql語句 19 Hibernate: 20 select 21 staff0_.id as id1_, 22 staff0_.name as name1_, 23 staff0_.deptId as deptId1_ 24 from 25 staff staff0_ 26 where 27 staff0_.deptId=? 28 [Staff [id=2, name=qqq1], Staff [id=3, name=qqq2], Staff [id=4, name=qqq3], Staff [id=5, name=qqq4], Staff [id=6, name=qqq5], Staff [id=7, name=qqq6], Staff [id=8, name=qqq7], Staff [id=9, name=qqq8], Staff [id=10, name=qqq9]]
這兩種方式度可以,不過在引數比較多的情況下,建議使用別名,那樣更加清楚,不易出錯,在少量引數時可以使用索引。
1.4、QBC檢索方式
QBC:Query By Criteria,是一種更加物件導向的查詢語言,提供的一系列QBC API來檢索物件。
HQL所能做的事情,使用QBC也大多能做用,這個通過例項來看看QBC是如何使用的。
步驟:
1>獲得session
2>session.createCriteria(Obejct.class); 建立criteria物件
3>使用criteria的API方法進行條件的增加。add(Restrictions.eq(屬性名,值))
4>執行查詢
list():返回一個集合列表,有可能集合中裝的是陣列,有可能是POJO物件。
uniqueResult():返回一個查詢結果,在已知查詢結果只有一個或者0個時,使用是沒有問題的,如果返回結果有多個,那麼就會報異常
例子一:使用QBC來對Staff進行查詢
1 //使用QBC,更加物件導向,不用寫sql語句。要查詢什麼,就直接將其類.class當作引數就能查詢出來 2 Criteria QBCCriteria = session.createCriteria(Staff.class); 3 List<Staff> staffList = QBCCriteria.list(); 4 for(Staff staff : staffList){ 5 System.out.println(staff.toString()); 6 } 7 //結果 8 Hibernate: 9 select 10 this_.id as id1_0_, 11 this_.name as name1_0_, 12 this_.deptId as deptId1_0_ 13 from 14 staff this_ 15 Staff [id=2, name=qqq1] 16 Staff [id=3, name=qqq2] 17 Staff [id=4, name=qqq3] 18 Staff [id=5, name=qqq4] 19 Staff [id=6, name=qqq5] 20 Staff [id=7, name=qqq6] 21 Staff [id=8, name=qqq7] 22 Staff [id=9, name=qqq8] 23 Staff [id=10, name=qqq9]
例子二:使用QBC來對Staff進行條件查詢
1 //使用QBC,對Staff進行查詢 2 Criteria QBCCriteria = session.createCriteria(Staff.class); 3 //add()新增條件,通過Restrictions(欄位名,值),由於確定是1行記錄,所以直接用uniqueResult() 4 Staff staff = (Staff) QBCCriteria.add(Restrictions.eq("id",3)).uniqueResult(); 5 6 System.out.println(staff.toString()); 7 8 //結果 9 Hibernate: 10 select 11 this_.id as id1_0_, 12 this_.name as name1_0_, 13 this_.deptId as deptId1_0_ 14 from 15 staff this_ 16 where 17 this_.id=? 18 Staff [id=3, name=qqq2]
例子三:QBC也能進行連線查詢
1 // from Staff inner join dept d ON 後面是hibernate自動幫我們填寫; 2 Criteria criteria = session.createCriteria(Staff.class); 3 //createAlias預設是內連線,可以不用寫。可以為dept表取別名,也可以不取。 4 criteria.createAlias("dept", "d", Criteria.INNER_JOIN); 5 List list = criteria.list(); 6 System.out.println(list); 7 8 //結果 9 Hibernate: 10 select 11 this_.id as id1_1_, 12 this_.name as name1_1_, 13 this_.deptId as deptId1_1_, 14 d1_.id as id0_0_, 15 d1_.name as name0_0_ 16 from 17 staff this_ 18 inner join 19 dept d1_ 20 on this_.deptId=d1_.id 21 [oneToMany.Staff@6a155d66, oneToMany.Staff@55a7e5ae, oneToMany.Staff@1d82e71, oneToMany.Staff@17d0fda9, oneToMany.Staff@19bd6e76, oneToMany.Staff@639f122d, oneToMany.Staff@60627b73, oneToMany.Staff@6196ec74, oneToMany.Staff@7b7de5b9]
給一張表來看看qbc增加的條件查詢語句。
重點有一個離線Criteria物件的用法。
1、在web層封裝查詢條件到離線Criteria物件中,將其DetachedCriteria物件繫結到Thread上。
2、到dao層,就能通過Thread拿到該離線Criteria物件,然後建立session。將session給DetachedCriteria,就能夠執行查詢
程式碼:
WEB層
DetachedCriteria detachedCriteria =DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.eq("name", "kitty"));
DAO層
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
// 將離線查詢物件 關聯到Session
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
Customer customer = (Customer) criteria.uniqueResult();
1.5、本地SQL檢索方式
使用標準的SQL語句來編寫。
步驟:
1>獲得session
2>編寫sql語句
3>session.createSQLQuery(sql);獲取SQLQuey物件
4>給sql語句設定引數。
5>執行查詢
list():返回一個集合列表,集合中裝的是Object[]。
返回實體類物件集合,如果與實體類進行了繫結,也就是使用了addEntity(xxx.class)。
例子一:查詢Staff的所有記錄
1 //使用的就是資料庫表名了。 2 SQLQuery SQLquery = session.createSQLQuery("select * from staff"); 3 //返回的是一個List<Object[]> 其中如果使用的SQL的話, 4 //後面不能夠通過獲得陣列然後在轉換為物件。只有通過addEntity。來繫結實體。 5 List list = SQLquery.list(); 6 System.out.println(list); 7 8 //結果 9 Hibernate: 10 select 11 * 12 from 13 staff 14 [[Ljava.lang.Object;@2c8938a8, [Ljava.lang.Object;@64e6b46f, [Ljava.lang.Object;@66501729, [Ljava.lang.Object;@1420b939, [Ljava.lang.Object;@70605781, [Ljava.lang.Object;@45110fca, [Ljava.lang.Object;@6323ba32, [Ljava.lang.Object;@3e955b77, [Ljava.lang.Object;@3fa801ba]
例子二:查詢Staff的所有記錄,並且繫結實體。 addEntity。
1 //使用的就是資料庫表名了。 2 SQLQuery SQLquery = session.createSQLQuery("select * from staff"); 3 //返回的是一個List<Object[]> 只有通過addEntity。來繫結實體。 4 List<Staff> list = SQLquery.addEntity(Staff.class).list(); 5 System.out.println(list.get(0).getName()); 6 7 //結果 8 Hibernate: 9 select 10 * 11 from 12 staff 13 qqq1
二、總結
以上就是我們說的5種檢索,其中說的重點就是hql的用法,上面的例子全部寫完了差不多就對hql有一定的瞭解。記住hql是對pojo類進行操作,而不是對資料庫中的表。在使用連線查詢時,可以使用QBC,因為更簡單,只需要用createAlias()就能使用任何的連線。一般在開發中sql語句都會提取出來放到hbm中,例如
在hbm對映檔案 (也可以用註解配置)
<!-- 這裡可以定義命名查詢 -->
<!-- 定義 HQL 語句 <query name=""></query> -->
<!-- 定義 SQL 語句 <sql-query name=""></sql-query> -->
<query name="findCustomerByName">
<![CDATA[from Customer where name = ?]]>
</query>
* 為hql語句 起了一個名字
程式程式碼:
//相當於把sql語句分離開來了。方便維護
Query query = session.getNamedQuery("findCustomerByName");
query.setParameter(0, "tom");
Customer customer = (Customer) query.uniqueResult();