NHibernate Step by Step (五)Criteria Query

NHibernate Step by Step (五)Criteria Query
可能很多人象我一樣,剛開始接觸HQL時,腦袋一片混沌,這是什麼語法嘛!!之所以這樣,是因爲我們總是會先入爲主地將之與SQL想比,雖然HQL看起來很SQL,而且設計時就有這樣的意圖,但是畢竟是兩種差別很大的東西,難免就會出現理解偏差的問題。好了,我們今天就不讓大家腦袋發暈了,HQL我們暫時放一放。今天我們來說另外一種查詢方法:
Criteria Query.
什麼是Criteria Query?簡單說,就是將我們的查詢條件封裝爲一個預定義的查詢對象,由這個查詢對象來執行查詢,而不用我們再去寫HQL了,而且更接近我們貫常的編程習慣。
是不是很不錯?讓我們來look look:
 
//創建關聯到某個類的查詢對象
ICriteria criteria = session.CreateCriteria(typeof(Person));

//添加表達式
criteria.Add(Expression.Eq("Name","Jackie Chan"));

IList list 
= criteria.List();
 
注意這一句:
 
Expression.Eq("Name","Jackie Chan")
 
Eq是Equal的縮寫,意思是添加一個查詢表達式,Person.Name = “Jackie Chan”
對應HQL就是:
from Person p where p.Name=”Jackie Chan”
NHibernate會在運行時動態生成類似上面的HQL,我們可以在配置文件把show-sql打開,觀看生成的SQL。
這樣是不是感覺清晰多了?又回到我們以前的編碼習慣了!
 
爲了對應HQL的種種查詢條件,NHibernate預定義了大量的Expression方法,我們列幾個如下:
 
Eq          = Equal
Gt          
= Greater than
Lt          
= Less than
Like        
= Like
Not         
= Not
IsNull      
= Is Null

基本上對應了大部分
HQL的語義,詳細的說明請參考api。
 
下面,我們詳細介紹Criteria的用法。
1. Example查詢
我們常常有這樣的查詢頁面:
用戶可以輸入“姓名”、“性別”、“年齡”等等來進行查詢,而我們常常的做法就是如下的煩瑣:
string condition = “”;
if(txtName.Text != null)
        condition 
+= “ Name=” + txtName.Text;

if(txtSex.Text != null)
       condition 
+= “ and Sex=” + txtSex.Text;

……


代碼看起來實在是不甚美觀,有什麼解決辦法呢?
Criteria提供了專爲這種問題而設計的Example查詢,如下:

ICriteria criteria = session.CreateCriteria(typeof(Person));

Person person 
= new Person();
person.Name 
= "Jackie Chan";
person.Age 
= 50;

//創建一個Example對象
criteria.Add(Example.Create(person));
IList list 
= criteria.List();
 
請注意:
 
criteria.Add(Example.Create(person));
 
這句代碼的意思是通過構造的person對象的屬性來生成表達式,實際生成的代碼如下:
 
SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE (this.age = @p0)
 
對應上面的問題,我們簡單地new出一個person對象,然後填充其屬性即可,不用再去構造那醜陋的條件判斷語句了!
 
2. 排序
我們想對返回的list進行排序,該怎麼辦呢?如下:
ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.Add(Expression.Gt(
"Age"20)); 

//添加一個排序對象
criteria.AddOrder(Order.Asc("Age"));

IList list 
= criteria.List();

 
請注意:
 
criteria.AddOrder(Order.Asc("Age"));
 
這句代碼的意思是在criteria上構造一個排序對象,並以Age屬性做正序排列,NHibernate在運行時會生成如下語句:
 
SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE this.age > @p0 ORDER BY this.age asc
 
如你所猜想,Order類肯定有另外一個“Desc“方法:)
 
3. 限制記錄範圍
在顯示大量的記錄時,我們常常採用的方法就是分頁,如果用NHibernate來做,該怎麼辦呢?
如下代碼:
ICriteria criteria = session.CreateCriteria(typeof(Person));

//從第10條記錄開始取
criteria.SetFirstResult(10);

//取20條記錄
criteria.SetMaxResults(20);

IList list 
= criteria.List();
 
這樣,我們就達到了分頁的目的。
注意:
NHibernate的分頁機制實際上依賴於不同的數據庫實現,所以,對特定的某種數據庫,並不一定是效率最好的,比如對SQLServer(爲什麼受傷的總是俺?爲什麼總是說俺比不上Oracle?俺都趕在2005年年底出2005版本了!!)。想知道爲什麼嗎?很簡單,check一下上面代碼生成的SQL就清楚了!或者深入點再看看NHibernate的分頁代碼,我就不解釋了,自己動手,豐衣足食:)
 
 
總體來講,Criteria對我們來說更熟悉,更容易上手,但是目前Criteria還是不夠完善——將對應的HQL一一封裝實在太煩瑣了,所以NHibernate還是以HQL查詢爲主,我們在使用的時候則看需要了,要麼使用HQL,要麼HQL和Criteria混合使用,重要的是解決問題,對不?
 
好了,這一篇就講這麼多,我們下次再接着練習。
任何建議或者批評,請e:[email protected]
 
 
posted on 2006-04-26 21:24 abluedog 閱讀(4416) 評論(18)  編輯 收藏 所屬分類: NHibernate
#1樓  2006-04-27 09:10 iokala [未註冊用戶]
很好,期待繼續   回覆  引用  查看    
Very Good 學習!   回覆  引用  查看    
#3樓  2006-04-27 10:40 發芽的豆子      
很好 。。。。   回覆  引用  查看    
#4樓  2006-04-27 13:31 pwei [未註冊用戶]
NHibernate中怎麼使用存儲過程?   回覆  引用  查看    
#5樓  2006-04-27 17:04 pwei [未註冊用戶]
我用Criteria的Example查詢查不到結果,怎麼回事?

[TestMethod]
public void CriteriaExample()
{
Person per = new Person();
per.Id = 4;
ICriteria criteria = session.CreateCriteria(typeof(Person));
criteria.Add(Example.Create(per));

IList list = criteria.List();

Assert.AreNotEqual(0,list.Count, "fail");
}

請問哪寫錯了?   回覆  引用  查看    
#6樓  2006-04-27 17:05 pwei [未註冊用戶]
另外,很期待你的下一篇文章,能不能快點,大哥?   回覆  引用  查看    
#7樓 [樓主] 2006-04-27 20:47 abluedog      
@pwei
Example.create:Version properties, identifiers and associations are ignored. By default, null valued properties are excluded.   回覆  引用  查看    
#8樓  2006-04-28 09:39 pwei [未註冊用戶]
@abluedog
是不是我上面寫的方法轉換成HQL之後並不只是ID這一個參數?
如果是的話,怎麼樣才能達到我想要的效果呢?   回覆  引用  查看    
#9樓  2006-04-28 09:44 pwei [未註冊用戶]
現在NHibernate的最新版本號是多少?
我的是在你第一篇文章中的地址下載的   回覆  引用  查看    
#10樓  2006-05-12 16:42 mzl [未註冊用戶]
1.0.2吧.   回覆  引用  查看    
#11樓  2006-06-07 18:10 家中慢步      
abluedog,老兄,繼續啊,怎麼四月之後就沒有下文了?期待你的spring.net系列   回覆  引用  查看    
#12樓  2006-11-26 17:50 IT獵人      
在試了樓主的示例後,發現幾處不對的地方:
1.SELECT this.id as id0_, this.name as name0_, this.age as age0_ FROM Person this WHERE (this.age = @p0)應該是
SELECT this.id as id0_, this.age as age0_, this.name as name0_ FROM Person this WHERE (this.age = @p0 and this.name = @p1)
2.//從第10條記錄開始取
criteria.SetFirstResult(10);
這裏不應該是說從第10條開始,而就是第11條,
criteria.SetFirstResult(9);纔是第10條.NHibernate中是從0開始計數的.
  回覆  引用  查看    
#13樓  2006-12-30 14:58 bondy [未註冊用戶]
誰有code smith啊,謝謝發一個給我 [email protected]
不勝感激....   回覆  引用  查看    
能不能問一下,你的Order 還有Example在那個命名空間下啊   回覆  引用  查看    
#15樓 [TrackBack] 2007-07-15 13:53 大冰
NHibernateStepbyStep(五)CriteriaQuery NHibernateStepbyStep(五)CriteriaQuery 可能很多人象我一樣,剛開始...
[引用提示]大冰引用了該文章, 地址: http://www.cnblogs.com/hanbing768/archive/2007/07/15/818697.html   回覆  引用  查看    
#16樓 [TrackBack] 2007-07-24 17:27 MichaeL
NHibernateStepbyStep(五)CriteriaQuery 轉載地址:http://www.cnblogs.com/abluedog/archive/2006/04/26/3...
[引用提示]MichaeL引用了該文章, 地址: http://www.cnblogs.com/MichaelLu/archive/2007/07/24/829714.html   回覆  引用  查看    
#17樓  2008-02-25 22:47 木獨豬      
還有沒有下篇?樓主,期待,寫的非常好!   回覆  引用  查看    
#18樓  2008-03-01 13:24 heize      
我想弱弱的問一下..你說的構造person對象那段.....不判斷是否爲空.怎麼知道填不填充這個屬性呢?   回覆  引用  查看    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章