Hibernate Criteria對象詳解

1.序言
Hibernate框架是目前JavaEE軟件開發的企業主流框架,學習Hibernate必然要掌握ORM(對象關係映射Object/Relation Mapping)的概念思想, Hibernate擁有完全的ORM理念,我們在操作數據庫時,可以通過面向對象的方式就可以完成數據庫的CRUD(創建(Create)、更新(Update)、讀取(Read)和刪除(Delete))操作。
企業在使用Hibernate進行軟件開發進行數據查詢時,主要基於HQL(Hibernate 面向對象的查詢語言,語法類似SQL)、 Criteria(面向對象的條件查詢對象)、SQL(原生態SQL語句)幾種方式,本文重點講解Criteria 這種完全面向對象編程查詢方式,詳細分析Crieria各種使用與SQL生成關係。
2.Criteria牛刀小試 
Criteria 是一個完全面向對象,可擴展的條件查詢API,通過它完全不需要考慮數據庫底層如何實現、SQL語句如何編寫,是Hibernate框架的核心查詢對象。
Hibernate 定義了CriteriaSpecification接口規範用來完成面向對象的條件查詢,Criteria 就是CriteriaSpecification的子接口。
 2.1創建數據庫環境 
我們以部門(Department)和員工(Employee) 案例,來講解Criteria的詳細使用。
部門表 department 
使用mysql5.x數據庫 
數據庫 hibernate3 
用戶名 root 
密碼 abc 
部門表 employee 
CREATE TABLE `department` (
   `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) default NULL,
   PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

員工表 department 

CREATE TABLE `employee` (

`id` int(11) NOT NULL auto_increment,

`name` varchar(255) default NULL,

    `age` int(11) NOT NULL,

    `birthday` date default NULL,

    `department_id` int(11) default NULL,

     PRIMARY KEY  (`id`),

     FOREIGN KEY (`department_id`) REFERENCES `department` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

2.2.使用JPA註解配置實體類

部門類 Department

員工類 Employee

2.3使用Crteria查詢所有部門和所有員工

2.3.1查詢所有部門

產生的SQL語句:

查詢所有員工

產生的SQL語句:

當session.createCriteria(實體類.class) 就會產生一條select所有列from 表;SQL語句,查詢實體類對應數據表的所有記錄,然後我們就可以在這個Criteria對象上進行條件查詢、分頁查詢、多表關聯查詢、投影查詢、子查詢等一系列操作……

3.Criteria SQL定製詳解

3.1對查詢添加條件對象Criterion

org.hibernate.criterion.Criterion是Hibernate提供的一個面向對象查詢條件接口,一個單獨的查詢就是Criterion接口的一個實例,用於限制Criteria對象的查詢,在Hibernate中Criterion對象的創建通常是通過Restrictions 工廠類完成的。

Restrictions 提供條件查詢方法:

例如: 

1、查詢姓“張”的所有員工信息 

產生的SQL語句

2、查詢年齡大於24的所有員工 

產生的SQL語句: 

3、查詢年齡小於28的姓“王”的員工

產生的SQL語句:

對於多個查詢條件,Restrictions提供了邏輯組合查詢方法。

and(Criterion lhs, Criterion rhs) 用於生成多個條件and關係SQL語句; 

or(Criterion lhs, Criterion rhs) 用於生成多個條件or關係SQL語句;

not(Criterion expression) 用於查詢與條件相反的數據,生成not取反查詢語句。

3.2分頁操作 firstResult和maxResults 

Criteria接口提供用於分頁查詢的方法,實現數據庫SQL物理級別的分頁操作。

setFirstResult(int firstResult)設置記錄的起始位置0代表第一條記錄。

setMaxResults(int maxResults)設置查詢記錄的長度。

例如:我要查詢1-10條件記錄firstResult爲0 ,maxResult爲10。

產生的SQL語句 

3.3排序操作 Order 

 Hibernate提供org.hibernate.criterion.Order用於排序操作, Criteria 接口提供addOrder(Order order)用於生成排序SQL

例如:查詢所有員工信息,按照年齡升序排列

產生的SQL語句:


3.4多表關聯操作 createAlias和createCriteria 

Criteria接口提供createAlias 和 createCriteria 兩組方法用於完成多表關聯查詢。

createAlias(String associationPath, String alias) 採用內連接關聯。

createAlias(String associationPath, String alias, int joinType) 可以通過joinType指定連接類型。

createCriteria(String associationPath) 採用內連接關聯(返回新的Criteria對象)。

createCriteria(String associationPath, int joinType) 可以通過joinType指定關聯類型(返回新的Criteria對象 )。 

例如:查詢部門爲“人力資源部”的所有員工。

方法一:使用createCriteria方法。 

產生的SQL語句:

代碼中的criteria對象,是針對employee表,criteria.createCriteria(”department”) 就是建立employee表和department表的內連接。返回的是針對department表新的criteria2對象,這時再對criteria2 添加條件,就是查詢department部門表的屬性,而不是employee的屬性了。 

方法二:使用createAlias 方法。 

使用createAlias方法不會像createCriteria那樣返回一個新的Criteria對象,alias只是對關聯表進行別名設置,通過別名引用設置屬性。 

產生的SQL語句

 3.5.投影、分組查詢 Projection 

在實際開發中,進行查詢是:可能只需要返回表中的指定列信息(投影)或者進行統計查詢(count、avg、sum、min、max),Criteria接口提供setProjection(Projection projection)方法用於實現投影查詢操作。 

org.hibernate.criterion.Projections工廠類用於返回Projection投影查詢對象。

例如: 1. 查詢員工表的name和age屬性。

產生的SQL語句

  Projections.property(屬性名)也可以寫爲Property.forName(屬性名 )。

2.查詢員工的總數量。 

      Projections提供了分組函數的查詢方法: 

   rowCount() 查詢記錄總數量;

   count(String propertyName) 統計某列數量;

   countDistinct(String propertyName) 統計某列數量(排除重複);

   avg(String propertyName) 統計某列平均值; 

   sum(String propertyName) 對某列值求和;

   max(String propertyName) 求某列最大值; 

   min(String propertyName) 求某列最小值。

產生的SQL語句 

3.查詢每個部門的員工數量(輸出部門的編號和數量 )。

Projections提供groupProperty(String propertyNam

-e)用於執行分組操作。

 

產生的SQL語句:

3.6. 設置結果集封裝策略 ResultTransformer 

剛剛說了投影操作的使用,其實在Hibernate內部投影查詢是會影響到結果集的封裝策略的。先用HQL舉例說明:

session.createQuery(”from Employee”).list(); 返回 List 

session.createQuery(”select count(e) from Employee e”).list(); 返回List

session.createQuery(”select name,age from Employee”).list(); 返回List 

從這幾個例子我們不難發現,如果沒有指定select語句(沒有投影),那麼將返回表中的所有字段,返回結果會被封裝到Entity實體對象Employee中,一但提供select語句(投影)後,返回的結果類型,將不再封裝到Employee對象,而是根據投影的實際類型返回,這就是投影對結果封裝策略的影響。 

我們再來看之前寫過的Criteria 查詢案例:

session.createCriteria(Employee.class).list();返回 List 

session.createCriteria(Employee.class).setProjection(

Projections.projectionList()

.add(Property.forName(”name”))

.add(Property.forName(”age”))); 返回 List 

投影之後,返回的結果將不再被封裝到Employee對象中,這是爲什麼呢? 

我們一起來看看 Criteria的接口定義,不難發現在Criteria接口中提供了一個setResultTransformer(ResultTransformer resultTransformer),這個ResultTransformer就是結果集轉換策略接口,在Criteria的父接口中CriteriaSpecification定義了幾個ResultTransformer的常用實現。 

ALIAS_TO_ENTITY_MAP 將結果集封裝到Map對象; 

ROOT_ENTITY 將結果集封裝到根實體對象;

DISTINCT_ROOT_ENTITY 將結果集封裝到不重複的根實體對象;

PROJECTION 根據投影的結果類型自動封裝; 

當進行投影查詢時,結果的封裝策略由ROOT_ENTITY 變爲了PROJECTION, 所以是根據查詢數據進行封裝,而不是封裝到根對象。

瞭解上面原理後,即使只查詢name和age屬性,也可以封裝成List集合。

使用AliasToBeanResultTransformer 修改結果封裝策略,AliasToBeanResultTransformer 會根據返回列自動匹配類中屬性名,完成封裝。

產生的SQL語句:

轉自:http://bbs.itcast.cn/article-211-1.html
發佈了36 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章