hibernate—QBC

QBC查詢就是經過使用Hibernate提供的Query By Criteria API來查詢對象,這種API封裝了SQL語句的動態拼裝,對查詢提供了更加面向對象的功能接口。咱們看下面的示例程序:sql

Criteria criteria=session.createCriteria(User.class);   criteria.add(Expression.eq(「name」,」zx」));   criteria.add(Expression.eq(「age」,new Integer(27));   List list=criteria.list();

當執行criteria.list()時會生成相似這樣的SQL語句:數據庫

Select * from user where name=’zx’   and   age=27;

因此在這裏咱們能夠看出,Criteria其實是一個查詢容器,它對查詢條件表達式的添加進行了封裝,具體的查詢條件是經過add()方法添加 的,並且具體的查詢條件的表達式運算是經過Expression指定的。Hibernate在運行期會根據Criteria指定的表達式條件來添加查詢條 件,而且生成查詢語句。這種方式很是符合Java以及全部面向對象編程語言的編程方式,因此大多數的持久層框架都提供了對這種方式查詢的支持。下面咱們講 解這種查詢方式的各個技術細節。express

一、Criteria查詢表達式: 編程

正如咱們所見,Expression對查詢語句的表達式進行了封裝和限制,下表列出了Expression全部的方法,以及每一個方法所對應的查詢表達式及其限制。session

方法描述
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指定。框架

注意:Expression各方法中的屬性參數(各方法中的第一個參數)所指定的屬性名稱(如:name,sex),並非數據庫表中的實際字段名稱,而是實體對象中映射實際數據表字段的類屬性名稱。

二、示例查詢: 編程語言

示例查詢是經過Example類來完成的,Example類實現了Criterion接口,能夠用做Criteria查詢條件,Example類的做用是:根據已有對象,查詢屬性值與之相同的其餘對象。以下代碼所示:hibernate

Criteria criteria=session.createCriteria(User.class);   User exampleuser=new User(「zx」);   criteria.add(Example.create(exampleuser));   List list=criteria.list();   for(int i=0;i   User user=(User)list.get(i);   System.out.println(user.getName()+」\n」);   }

上述代碼中User exampleuser=new User(「zx」);criteria.add(Example.create(exampleuser));兩句至關於 criteria.add(Expression.eq(「name」,」zx」));所以會生成相似以下的SQL語句:code

select * from user where name=’zx’;

在上面的代碼中exampleuser稱爲示例對象。

在Hibernate中隊示例查詢,默認狀況下會排除掉示例對象中屬性值爲 空的屬性,還能夠調用Example.excludeNone(排除空串值)/excludeZeros(排除零值),或者調用 Example.excludeProperty方法來指定排除特定屬性。對象

示例查詢主要應用於組合查詢中,好比根據用戶輸入的查詢條件動態生成最終的查詢語句,經過使用示例查詢,能夠避免因爲查詢條件過多而寫的大量if判斷語句。

三、複合查詢:

複合查詢主要是處理,具備關聯關係的兩個實體怎樣進行關聯查詢,好比User實體對象與Addres實體對象具備一對多的關聯關係,咱們能夠以下構造符合查詢:

Criteria criteria=session.createCriteria(User.class);   Criteria addcriteria=criteria.createCriteria(「addresses」);(1)   addcriteria.add(Express.like(「address」,」%tianjin%」));     List list=criteria.list();   for(int i=0;i     User user=(User)list.get(i);     System.out.println(user.getName()+」\n」);     Set addresses=user.getAddresses();     Iterator it=addresses.iterator();     while(it.hasNext(){   Address address=(Address)it.next();   System.out.println(address.getAddress()+」\n」);     }   }

當執行到了(1)處時,代表要針對User對象的addresses屬性添加新的查詢條件,所以當執行criteria.list()時,Hibernate會生成相似以下的SQL語句:

Select * from user inner join address on user.id=address.id where   address.address like ‘%shanghai%’;

正如咱們所見,咱們能夠經過向Criteria中添加保存關聯對象的集合屬性(addresses屬性保存與User對象相關聯的Address對象),來構造複合查詢,在數據庫一端是經過內鏈接查詢來實現。

四、Criteria的高級特性:

A、限定返回記錄條數:

咱們能夠經過利用Criteria.setFirstResult/setMaxResult方法來限定返回某一次查詢的記錄數,以下代碼:

Criteria criteria=session.createCriteria(User.class);   criteria.setFirstResult(100);   criteria.setMaxResult(200);

經過以上代碼能夠設定該次查詢返回user表中的從第100條記錄開始直到第200條記錄結束的100條記錄。

B、對查詢結果進行排序:

可經過使用net.sf.hibernate.expression.Order類能夠對查詢結果集進行排序,以下面代碼:

Criteria criteria=session.createCriteria(User.class);   criteria.add(Expression.eq(「groupid」,」2」);   criteria.addOrder(Order.asc(「name」));   criteria.addOrder(Order.desc(「groupid」));   List list=criteria.list();

經過使用Order類的asc()/desc()方法,能夠指定針對某個字段的排序邏輯,若是執行上述代碼,會生成相似以下的SQL語句:

Select * from user where groupid=’2’ order by name asc,groupid desc

C、分組與統計:

在Hibernate3中,對Criteria又增添了新功能,能夠支持分組與統計功能,在Hibernate3中增長了Projections以及ProjectionList類,這兩個類對分組與統計功能進行了封裝,以下代碼:

Criteria criteria=session.createCriteria(User.class);   criteria.setProjection(Projections.groupProperty(「age」));(1)   List list=criteria.list();   Iterator it=list.iterator();   while(it.hasNext()){    System.out.println(it.next());   }

經過(1)處的代碼,咱們經過Projections類指定了用於分組的目標屬性,當進行檢索時Hibernate會生成相似以下的SQL語句:

Select age from user group by age;

還能夠經過使用Projections的avg()/rowCount()/count()/max()/min()/countDistinct()等方法來實現統計功能,以下面的代碼示例:

Criteria criteria=session.createCriteria(User.class);   criteria.setProjection(Projections.avg(「age」));(1)   List list=criteria.list();   Iterator it=list.iterator();   while(it.hasNext()){    System.out.println(it.next());   }

經過(1)處的代碼,咱們實現了對用戶平均年齡的統計,當進行檢索時,Hibernate會生成相似以下的SQL語句:

Select avg(age) from user;

另外,在SQL語句中的多條件分組與統計功能,能夠利用ProjectionList類來實現,以下面代碼所示:

Criteria criteria=session.createCriteria(User.class);   ProjectionList prolist=Projections.projectionList();   prolist.add(Projections.groupProperty(「age」));   prolist.add(Projections.rowCount());   criteria.setProjection(prolist);   List list=criteria.list();

經過以上代碼,實現了對不一樣年齡人員數量的分組統計,當進行檢索時,Hibernate會生成相似以下的SQL語句:

Select age,count(*) from user group by age;

五、DetachedCriteria:

在Hibernate2中,Criteria實例是與建立它的Session實例具備相同的生命週期的,也就是說,Session實例是它所建立的 Criteria實例的宿主,當Session關閉時,寄生於Session實例的Criteria都將失效。這就對Criteria的重用形成了困難, 爲了實現Criteria實例的重用,在Hibernate3中提供了一個DetachedCriteria類,DetachedCriteria實例的 生命週期與Session實例的生命週期無關,咱們能夠利用DetachedCriteria對一些經常使用的Criteria查詢條件進行抽離,當須要進行 檢索時再與Session實例關聯,從而得到運行期的Criteria實例。以下面的代碼所示:

DetachedCriteria dc= DetachedCriteria.forClass(User.class);   dc.add(Expression.eq(「name」,」zhaoxin」));   dc.add(Expression.eq(「sex」,」1」));   Criteria criteria=dc.getExecutableCriteria(session);   Iterator it=criteria.list().iterator();   while(it.hasNext()){     User user=(User)it.next();     System.out.println(user.getName());   }

正如咱們所見,DetachedCriteria的生存週期與session實例無關,當須要進行檢索時,經過getExecutableCriteria(session)方法,與當前的Session實例關聯並得到運行期的Criteria實例,完成檢索。

DetachedCriteria也能夠用於完成子查詢功能,以下代碼所示:

DetachedCriteria dc= DetachedCriteria.forClass(User.class);   dc.setProjection(Projections.avg(「age」));   Criteria criteria=session.createCriteria(User.class);   criteria.add(Subqueries.propertyGt(「age」,dc));   List list=criteria.list();

經過Subqueries類,實現了添加子查詢的功能,咱們將DetachedCriteria所設定的查詢條件,看成子查詢添加到了運行時Criteria實例的查詢條件中,當執行檢索時Hibernate會生成相似以下的SQL語句:

Select * from user where age>(select avg(age) from user group by age);
相關文章
相關標籤/搜索