亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

Hibernate 中的 Criteria 查詢

1. 前言

今天給大家介紹一個絕對純正的 OOP 查詢方案:Criteria 查詢。通過本節課程的內容,你將了解到:

  • 什么是 Criteria 查詢
  • Criteria 實現復雜查詢;

2. Criteria 查詢

什么是 Criteria 查詢?

Criteria 查詢從字面翻譯就是標準查詢。所謂 標準查詢,指的是 HIbernate 提供了純正的 OOP API 查詢方案。不像 HQL 還摻雜了一些 SQL 層面的內容。

來一個查詢需求:查詢所有的學生。

想必這學生會很生氣,總是被搬來搬去的。

上實例之前,先認識 Hibernate 兄弟會中的一名新成員:Criteria。

在使用 Criteria 查詢之前,必須先創建 Criteria 對象:

Criteria cr = session.createCriteria(Student.class);
List<Student> stus = cr.list();

是不是很 OOP。使用 HQL 時,會有一種時空穿越的感覺 ,OOPSQL 語法交替出現,很容易犯暈。使用 Criteria 進行查詢時則不會。

而且,Criteria 不是一個人在戰斗,它也有屬于自己的兄弟會,為開發者提供了更強有力的支持。

先介紹一下它的幾個兄弟,并且它們的作用已經從字面告訴了你。

  • Criterion: 這位兄弟長得好生面熟,其實它就 Criteria 的單數存在形式;
  • Oder: 提供排序功能;
  • Restrictions: 限制、約束的意思,和 SQL 中的 where 關鍵字的作用是一樣。所以,它提供了很多類似于運算符的方法,可以對查詢數據進行過濾。

Criteria 面子上很 OOP ,但是無論你怎么逃,都是在 SQL 的手掌心,也就是說 Criteria 查詢最終還是會被 Hibernate 轉譯成 SQL 語句。

只要是使用關系型數據庫,SQL 就是逃不掉的宿命。只是直接、間接使用的區別。

所以,Criteria 查詢中總會找到 SQL 的影子。

2.1 基礎查詢

為了更好地理解它們,來一個實例:查詢姓名叫 “Hibernate” 的學生。

Criteria criteria = session.createCriteria(Student.class);
Criterion criterion = Restrictions.eq("stuName", "Hibernate");
criteria.add(criterion);
Student student = (Student) criteria.uniqueResult();
System.out.println(student);

Criteria 查詢封裝了關系型數據庫的概念,所以,一定要注意,使用方法進行數據過濾時,都是屬性進行比較。

確認查詢出來的數據只有一條記錄時,可以使用 uniqueResult() 方法。條件查詢的關鍵是了解 Restrictions,它所提供的很多類似于邏輯運算符的方法:

  • Restrictions.eq(): 相當于 =;
  • Restrictions.not(Exprission.eq()) : 相當于 <>;
  • Restrictions.le(): 相當于 <=;
  • Restrictions.gt(): 相當于 >;
  • Restrictions.ge(): 相當于 >=;
  • Restrictions.lt(): 相當于 <;
  • Restrictions.isnull(): 相當于 is null;
  • Restrictions.isNotNull(): 相當于 is not null ;
  • Restrictions.like(): 相當于 like;
  • Restrictions.and(): 相當于 and;
  • Restrictions.conjunction(): 相當于 and;
  • Restrictions.or(): 相當于 or;
  • Restrictions.disjunction() : 相當于 or;
  • Restrictions.not(): 相當于 not;
  • Restrictions.in(): 相當于 in;
  • Restrictions.not(Restrictions.in()): 相當于 not in;
  • Restrictions.between(): 相當于 between x and y;
  • Restrictions.not(Restrictions…between()) : 相當于 not between x and y。

如上方法,幾乎涵蓋了所有 SQL 條件運算符,任意組合上面方法,沒有查詢不出來的結果。

如查詢學生編號是 1 或 2 或 4 的學生。
使用 SQL,則是:

select * from student where stuId in (1,2,4)

使用 Criteria 查詢,則如下所示:

Criterion criterion = Restrictions.in("stuId",new Integer[] {1,2,4} );
criteria.add(criterion);

如查詢學生編號大于 2 且班級編號為 1 的學生。

使用 SQL:

select * from student where stuId>2 and classRommId=1

如果使用 Criteria 查詢,則先構建兩個約束對象:

Criterion criterion = Restrictions.gt("stuId", 2);
Criterion criterion1 = Restrictions.eqOrIsNull("classRoom.classRoomId", 1);

再把這兩個約束作為參數,構建一條聯合約束:

LogicalExpression logicalExpression = Restrictions.and(criterion, criterion1);
criteria.add(logicalExpression);

LogicalExpression API 用來表示一個邏輯表達式。是 Criterion 的子類。

比較原生 SQLCriteria 查詢,會發現原生 SQL 語句要簡單很多,使用 Criteria 查詢需要掌握很多 API,而且代碼量也比較大,這也可能是 Criteria 查詢得不到普及的原因吧。

但是,Hibernate 既然推出了這種查詢方案,想必也有它的考慮。比如說,創建動態查詢語句,這點原生 SQLHQL 都沒有 Criteria 好。

還是那句話,存在就是合理的。

如果,你對原生 SQL 有情懷,Criteria 查詢中也是可以用的。

criteria.add( Restrictions.sqlRestriction("stuId>2 and clasRoomId=1"));

注意,不要在 Sql 片段中使用 where 關鍵字。既然是原生 SQL,所以語句中是字段概念,而不是屬性概念

前面講解 HQL 時,提到了分頁查詢。Criteria 一樣可以實現分頁查詢,和 HQL 中分頁方法一樣:

Criteria criteria = session.createCriteria(Student.class);
criteria.setFirstResult(1);
criteria.setMaxResults(5);
List results = criteria.list();

2.2 高級查詢

排序查詢使用 order API 實現:

criteria.addOrder(Order.desc("stuId"));
criteria.addOrder(Order.asc("stuName"));

一樣,可以多字段排序。

使用聚合函數:聚合函數的功能封裝在 projections API 中:

criteria.setProjection(Projections.rowCount());
criteria.setProjection(Projections.avg("stuId"));
criteria.setProjection(Projections.max("stuId"));
criteria.setProjection(Projections.min("stuId"));
criteria.setProjection(Projections.sum("stuId"));

Criteria 也能實現關聯查詢:

Criteria criteria = session.createCriteria(Student.class);
criteria.add(Restrictions.like("stuName", "Hibernate%"));
Criteria criteria01 = criteria.createCriteria("classRoom");
criteria01.add(Restrictions.like("classRoomName", "c19%"));
List<Student> students = criteria.list();

可以把一個 Criteria 實例看成對一張表的查詢,如果需要關聯多張表,則可以通過一個 Criteria 再創建一個 Criteria 對象。

HibernateCriteria 查詢提供各種各樣的 API,適應于任何查詢需求,相比較使用的已經很普遍的 SQL 查詢,Criteria 查詢充滿了雞肋的味道。但對于動態查詢需求,Criteria 查詢的優勢又很明顯。

3. 原生 SQL 查詢

Hibernate 支持原生 SQL 查詢,對于熟悉并鐘情于 SQL 語句的開發者來講,是一個很大的福音。
實例:

String sql="select * from student";
SQLQuery sqlQuery= session.createSQLQuery(sql);

Hibernate 提供了一個與原生 SQL 有關的 SQLQuery 對象。SQLQueryQuery 的子類,可適應不同的原生 SQL 語句查詢。

4. 小結

本節課和大家聊到了 Criteria 查詢,HQL 查詢,原生 SQL 查詢。原生 SQL 查詢無所不能,HQL 查詢是面向對象的 SQL ,具有混血身份。據說,混血的總是很美,也是建議大家選擇的一種查詢方案。

Criteria 查詢是 Hibernate 提供的一種純面向對象的解決方案,但是,為了構建一條 SQL 語句需要寫許多代碼,其應用領域會相對較窄。

本節課給大家介紹 Criteria 的目的,一是擴展學生的學習范圍,如果需要使用動態查詢,Criteria 則有著無可比擬的優越感。