Hibernate 複合查詢

複合查詢主要是處理,具有關聯關係的兩個實體怎樣進行關聯查詢,比如 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 對象),來構造複合查詢,在數據庫一端是通過內連接查詢來實現。
 
相關:
1. Hibernate
2.

QBC 查詢:
   QBC 查詢就是通過使用 Hibernate 提供的 Query By Criteria API 來查詢對象,這種 API 封裝了 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 以及所有面向對象編程語言的編程方式,所以大多數的持久層框架都提供了對這種方式查詢的支持。下面我們講解這種查詢方式的各個技術細節。
1、 Criteria 查詢表達式:
正如我們所見, Expression 對查詢語句的表達式進行了封裝和限制,下表列出了 Expression 所有的方法,以及每個方法所對應的查詢表達式及其限制。
方法
描述
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 ),並不是數據庫表中的實際字段名稱,而是實體對象中映射實際數據表字段的類屬性名稱。
 
2、 示例查詢:
   示例查詢是通過 Example 類來完成的, Example 類實現了 Criterion 接口,可以用作 Criteria 查詢條件, Example 類的作用是:根據已有對象,查詢屬性值與之相同的其他對象。如下代碼所示:
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 語句:
select * from user where name=’zx’; 在上面的代碼中 exampleuser 稱爲示例對象。
   Hibernate 中隊示例查詢,默認情況下會排除掉示例對象中屬性值爲空的屬性,還可以調用 Example.excludeNone (排除空串值) /excludeZeros (排除零值),或者調用 Example.excludeProperty 方法來指定排除特定屬性。
   示例查詢主要應用於組合查詢中,比如根據用戶輸入的查詢條件動態生成最終的查詢語句,通過使用示例查詢,可以避免由於查詢條件過多而寫的大量 if 判斷語句。
3、 複合查詢:
複合查詢主要是處理,具有關聯關係的兩個實體怎樣進行關聯查詢,比如 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 對象),來構造複合查詢,在數據庫一端是通過內連接查詢來實現。
 
 
 
4、 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;
5、 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);
發佈了33 篇原創文章 · 獲贊 0 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章