hibernate QBC和QBE精講與案列分析(上)
轉載:http://blog.sina.com.cn/s/blog_7fff746d0101ese2.html
本章的主要內容包括:
● QBC資料檢索
● 連線查詢
● Hibernate的資料檢索策略
QBC資料檢索
Hibernate提供了另一種形式的面向物件的查詢方式QBC(Query by Criteria)。這種查詢是以函式API的方式動態地設定查詢條件,組成查詢語句。基本結構是session建立criteria介面,然後呼叫criteria介面的add函式,增加查詢條件(即
除了有當前session建立的criteria介面外,Hibernate還提供了在session不可用時,組織查詢語句的遊離態的DetachCriteria類,它的查詢條件設定與criteria類似,只是它不由session建立,而是在需要session可用時,再呼叫getExecutableCriteria()執行查詢。
另外,為了讓criteria的查詢方法與HQL一樣功能豐富,Hibernate還提供了projections類,用於提供各種函式來產生可以使用聚集函式,進行投影查詢和進行查詢結果設定的各種
圖8-1是Criteria相關類的結構圖。
圖8-1 Criteria相關類圖
由圖8-1可見,Criteria介面和DetachedCriteria類都繼承了CriteriaSpecification介面,開發人員在使用QBC查詢時,都是直接選擇用Criteria或DetachedCriteria。而它們兩個都是一樣使用可以設定各種查詢條件或者查詢結果的Criterion,Projection
8.1.1 QBC查詢主要類
下面分別對QBC查詢中使用的幾個主要介面和類進行介紹。
1. Criteria介面
Criteria呼叫add函式新增Criterion物件來組成查詢條件,然後根據查詢條件來查詢持久化類物件。與HQL查詢的Query類一樣,也是由Session呼叫createCriteria()函式建立。
以下程式碼是檢索價格大於25的Product物件。
Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.gt("price",new Double(25.0)));
List results = crit.list();
相應地,HQL實現的程式碼如下:
Query query = session.createQuery(
"from Product where price>:price");
query.setDouble("price",25.0);
List results = query.list();
使用Criteria查詢的步驟是:(ke ruai tie ria)
(1) 呼叫一個可用的session的createCriteria()方法建立Criteria物件,其中createCriteria()方法以被查詢的實體類型別作為引數。
(2) 根據需要使用add函式設定各種criterion查詢條件,使用setProjection設定projection
(3) 呼叫Criteria的list或者scroll方法即執行查詢語句,檢索資料庫,把查詢結果返回放在List或ScrollableResults中。
(4) 讀取List和ScrollableResults,即可取出查詢物件。
Criteria介面在呼叫List或者Scroll方法時執行資料庫檢索,返回結果可以是以List形式或者ScrollableResults形式,與Query相比,少了iterate()方法執行返回iterator形式的結果。另外,與Query類似,Criteria也可以使用setFlushMode、setCacheMode、setTimeOut等設定各種Criteria查詢的環境,可以使用setFirstResult()、setMaxResult()等方法設定檢索結果。
下面介紹在Query中沒有的,但在Criteria中使用的主要的函式:
(1) Criteria add(Criterion criterion)
用於新增查詢條件,相當於設定HQL中的where從句。當有多個查詢條件時,可以逐個增加。例如:
Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.gt("price",new Double(25.0)));
crit.add(Restrictions.gt("name","Clothes"));
List results = crit.list();
或者使用方法鏈程式設計風格:
List results=session.createCriteria(Product.class)
.add(Restrictions.gt("price",new Double(25.0)))
.add(Restrictions.gt("name","Clothes"))
.list();
多個add相當於對查詢條件進行and操作,即要求同時滿足這些條件。
(2) Criteria addOrder(Order order)
如果需要排序,可以使用Criteria的addOrder()方法增加排序用的Order類。
(3) Criteria createAlias(String associationPath, String alias)
Criteria createAlias(String associationPath, String alias, int joinType)
List cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Restrictions.eqProperty("kt.name", "mt.name") ) .list();
用於設定連線查詢,第一種過載形式使用的是預設的內連線;第二種過載形式可以選擇連線方式。
associationPath:屬性的路徑,使用點“.”作為分割符。例如,Basiccar持久化類中有集合屬性persons,而persons中的元素是持久化類Person,而Person類中有集合屬性clotheses,其中存有關聯物件clothes,如果要從Basiccar物件關聯到clothes物件,屬性路徑就寫成:persons.clotheses,使用點隔開。
alias:關聯屬性的別名,後面可以使用這個別名來設定關聯條件。
joinType:連線查詢時選擇的關聯方式。joinType可以是內連線CriteriaSpecification.INNER_JOIN(預設值)、全連線CriteriaSpecification.FULL_JOIN, 或者左連線CriteriaSpecification.LEFT_JOIN。
(4) Criteria createCriteria(String associationPath)
Criteria createCriteria(String associationPath, int joinType)
Criteria createCriteria(String associationPath, String alias)
Criteria createCriteria(String associationPath, String alias, int joinType)
建立一個指向主類關聯的實體的criteria查詢,在進行存在關聯關係的物件檢索時會用到。
joinType可以指定關聯是內連線、左聯接還是全連線。alias則可以指定別名。
返回值是被建立的子查詢。
(5) Criteria setProjection(Projection projection)
如果需要使用投影查詢、聚集函式等,可以按需要生成Projection類,然後使用Criteria的setProjection()方法,對返回結果進行某些列的投影或聚集運算。
2. DetachedCriteria類
使用Criteria查詢需要當前有可用的session,但是,有時構造查詢語句時,並不一定能得到可用的session。例如,在分層的專案開發過程中,通常會在表現層,根據使用者選擇的條件,動態生成SQL語句,進行查詢。這個時候,表現層是得不到session的,但是它需要把構造好的查詢傳給業務層進行session查詢。DetachedCriteria就可以解決這個問題,即在表現層,應用程式使用DetachedCriteria來構造查詢條件,然後把這個detachedCriteria傳遞給業務層物件,讓業務層在session範圍內構造criteria查詢。所以,detachedCriteria在構造查詢時,session還不可用,detachedCriteria查詢面對的是遊離的POJO類,而Criteria查詢時面對的持久化物件,所以稱為detachedCriteria。以下是一個使用DetachedCriteria查詢的簡單例子。
DetachedCriteria detachedCriteria= DetachedCriteria.forClass (BasicCar.class); detachedCriteria.add(Restrictions.eq("id", new Integer(1)));
上面的程式碼片段先建立了一個DetachedCriteria的例項,然後只要在有可用的session時,使用它的getExecutableCriteria()方法,把這個可用的session關聯進來即可,它會返回一個在這個session內進行查詢的criteria類。程式碼如下所示:
Criteria crit=detachedCriteria.getExecutableCriteria(session);
List results = crit.list();
DetachedCriteria 提供了4個靜態方法forClass(Class)或forEntityName(Name)進行DetachedCriteria例項的建立。DetachedCriteria也提供了add(Criterion)、addOrder(Order)、setProjection(Projection)、createAlias()、createCriteria()等方法用於構造查詢及其返回結果,與Criteria提供的函式不同的是,DetachedCriteria類提供的函式返回也是DetachedCriteria 類。
3. Criterion和Retrictions類
Criterion被Criteria介面的add()方法呼叫,作為查詢條件。內建的Criterion型別由Restrictions這個工廠類提供。實現Criterion介面的可以用來作為查詢條件的類包括Expression、Example、Junction等。
Criterion的類圖關係如圖8-2所示。
圖8-2 Criterion相關類圖
4. Projection和Projections
Projection介面是Criteria查詢結果集的投影表示。內建的Projection類由Projections工廠類提供。實現projection介面的類包括AliasedProjection、Distinct、ProjectionList、SimpleProjection、SQLProjection等5個。Projection的類圖如圖8-3所示。
圖8-3 Projection相關類圖
Projection介面被作為Criteria的setProjection()函式的引數,對查詢結果進行選擇某些屬性的投影,進行avg、max、min、count、sum等聚集運算。
Projections提供多種靜態方法來產生對查詢的結果進行各種運算的projection例項。
表8-1列出了Projections提供的各種結果運算的函式,以及相應的HQL運算子。
表8-1 Projections的函式
意 思
Projections函式(重點)
HQL例子
1、計算平均值
avg(String?propertyName)
Select avg(o.property) from Object o
2、計算數目
count(String?propertyName)
Select count(o.property) from Object o
3、過濾相同值的屬性然後計算數目
countDistinct(String?propertyName)
Select count(distinct o.property) from Object o
4、過濾相同值的屬性
distinct(Projection?proj)
Select distinct o.property from Object o
5、按某個屬性分組
groupProperty(String?propertyName)
Criteria crit = session.createCriteria(BasicCar.class)
.setProjection(Projections.groupProperty("name"));
From Object o group by o.property
6、取物件的主鍵
id()
Select o.id from Object o
7、計算最大值
max(String?propertyName)
Select max(o.property) from Object o
8、計算最小值
min(String?propertyName)
Select min(o.property) from Object o
9、投影某個屬性
property(String?propertyName)
Select o.property from Object o
10、計算行數目
rowCount()
Select count(*) from Object o
11、計算總和
sum(String?propertyName)
Select sum(o.property) from Object o
5. Order(重點)
Order類提供對Criteria查詢結果集的排序,其靜態函式生成升序或降序的Order類,被作為Criteria的引數傳給addOrder()方法。
其主要函式有:
static Order asc(String propertyName) 按降序排
static Order desc(String propertyName) 按升序排
List cats = sess.createCriteria(Cat.class) .add( Restrictions.like("name", "F%") .addOrder( Order.asc("name") ) .addOrder( Order.desc("age") ) .setMaxResults(50) .list();
List cats = sess.createCriteria(Cat.class) .add( Property.forName("name").like("F%") ) .addOrder( Property.forName("name").asc() ) .addOrder( Property.forName("age").desc() ) .setMaxResults(50) .list();
8.1.2 使用Expression類和Example類設定查詢條件
下面分別介紹Expression類和Example類的查詢條件。
1.Expression類(瞭解)
Expression類由Restrictions工廠類的各個設定條件的靜態方法產生。例如,Restrictions類中的gt(String propertyName, Object value)靜態方法,用於設定某個屬性等於某個值的查詢條件,返回的SimpleExpression相當於where propertyName='value'的條件。
方法 |
描述 |
Expression.eq |
對應SQL的“field=value”表示式 如:Expression.eq(“name”,”zx”); |
Expression.allEq |
方法的引數為一個Map型別物件,包含多個名/值對對應關係,相當於多個Expression.eq的疊加 |
Expression.gt |
對應SQL的“field>value”表示式 |
Expression.ge |
對應SQL的“field>=value”表示式 |
Expression.lt |
對應SQL的“field”表示式 |
Expression.le |
對應SQL的“field<=value”表示式 |
Expression.between |
對應SQL語句的between表示式,如:查詢年齡在21與27歲之間的使用者,可以寫成Expression.between(“age”,new Integer(21),new Integer(27)); |
Expression.like |
對應SQL語句的”field like value”表示式 |
Expression.in |
對應SQL語句的“field in(……)”表示式 |
Expression.eqProperty |
用於比較兩個屬性值,對應”field=field”SQL表示式 |
Expression.gtProperty |
用於比較兩個屬性值,對應”field>field”SQL表示式 |
Expression.geProperty |
用於比較兩個屬性值,對應”field>=field”SQL表示式 |
Expression.ltProperty |
用於比較兩個屬性值,對應”field表示式 |
Expression.leProperty |
用於比較兩個屬性值,對應”field<=field”SQL表示式 |
Expression.and |
對應SQL語句的And關係組合,如:Expression.and(Expression.eq(“name”,”zx”),Expression.eq(“sex”,”1”)); |
Expression.or |
對應SQL語句的Or關係組合,如:Expression.or(Expression.eq(“name”,”zx”),Expression.eq(“name”,”zhaoxin”)); |
Expression.sql |
作為補充這個方法提供了原生SQL語句查詢的支援,在執行時直接通過原生SQL語句進行限定,如:Expression.sql(“lower({alias}.name) like (?)”,“zhao%”,Hibernate.STRING) ;在執行時{ alias }將會由當前查詢所關聯的實體類名替換,()中的?將會由”zhao%”替換,並且型別由Hibernate.STRING指定。 |
表8-2列出了Restrictions提供的各種條件設定,以及相應的HQL運算子。
表8-2 Restrictions的函式
意 思
Restrictions函式(重點)
HQL例子
1、查詢條件邏輯and運算
and(Criterion?lhs, Criterion?rhs)
From Object o where o.property1 = ? and o.property2=?
2、檢索在兩個數值之間的
between(String?propertyName, Object?lo,
Object?hi)
From Object o where o.property between ? and ?
3、等於
eq(String?propertyName, Object?value)
eqProperty(String?propertyName, String?otherPropertyName)
Eg: List cats = sess.createCriteria(Cat.class) .createAlias("kittens", "kt") .createAlias("mate", "mt") .add( Restrictions.eqProperty("kt.name", "mt.name") ) .list();
From Object o where
o.property=?
4、大於等於
ge(String?propertyName, Object?value)
geProperty(String?propertyName, String?otherPropertyName)
From Object o where
o.property>=?
5、大於
gt(String?propertyName, Object?value)
gtProperty(String?propertyName, String?otherPropertyName)
From Object o where
o.property>?
6、主鍵等於
idEq(Object?value)
Criteria crit = session.createCriteria(BasicCar.class)
.add( Expression.idEq(new Long(1)) );
From Object o where o.id=?
7、字串匹配,不區分大小寫
islike(String?propertyName, Object?value)
islike(String?propertyName, String?value, MatchMode?matchMode)
Criteria crit = session.createCriteria(BasicCar.class)
.add(Restrictions.islike("name","a", MatchMode.END));
List cats = sess.createCriteria(Cat.class) .add( Restrictions.like("name", "Fritz%") )
From Object o where lower
(o.property) like ??
(續表)
意 思
Restrictions函式
HQL例子
8、範圍運算
in(String?propertyName, Collection?values)
in(String?propertyName, Object[]?values)
From Object o where o.property in(‘a’,’b’…)
.add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
9、檢查物件的一個集合屬性是否為空,也就是在多對多或多對一雙向關聯中,“一”方對應的“多”方為空,沒有關聯的
isEmpty(String?propertyName)
From Object o where
o.properties is empty
10、檢查物件的一個集合屬性是否不為空
isNotEmpty(String?propertyName)
From Object o where
o.properties is not empty
11、一個屬性是否不為空
isNotNull(String?propertyName)
From Object o where o.property is not null
12、一個屬性是否為空
isNull(String?propertyName)
Criteria crit = session.createCriteria(BasicCar.class)
.add(Restrictions.isNull("name"));
From Object o where o.property
is null
13、小於等於
le(String?propertyName, Object?value)
leProperty(String?propertyName, String?otherPropertyName)
From Object o where
o.property<=?
14、字串匹配
like(String?propertyName, Object?value)
like(String?propertyName, String?value, MatchMode?matchMode)
Criteria crit = session.createCriteria(BasicCar.class)
.add(Restrictions.like("name","A%"));
From Object o where o.property
like ‘??’
15、小於
lt(String?propertyName, Object?value)
ltProperty(String?propertyName, String?otherPropertyName)
From Object o where
o.property