在學習動態SQL語句之前,首先必須對條件查詢有一定了解,先來學習如何向IBatis.Net的映射文件里傳入參數。
一、條件查詢
1、傳遞單個參數
如根據Id查詢:
<select id="SelectPersonById" resultMap="Person" parameterClass="Int32" > SELECT * FROM Person WHERE Id = #Id# --這樣傳入一個參數 </select>
調用的方法是:
PersonModel p = mapper.QueryForObject<PersonModel>("SelectPersonById", 3); //3就是傳到SQL語句中的參數
因此,最后生成的SQL語句為:
SELECT * FROM Person WHERE Id = 3
以上只最簡單的方式,我連parameterClass都沒。
2、傳遞多個參數
傳遞多個參數通常使用鍵值對,如HashTable或實體類。
1、鍵值對的方式
鍵值對的方式可以使用HashTable或Dictionary<TKey,TValue>,當為后者時映射文件中的parameterClass的值要為:System.Collections.IDictionary。
<select id="SelectPersonById" resultMap="Person" parameterClass="HashTable"> SELECT * FROM Person WHERE Id = #Id# AND Name = #Name# </select>
調用方法:
Hashtable ht = new Hashtable(); ht.Add("Id",1); ht.Add("Name","劉備"); PersonModel p = mapper.QueryForObject<PersonModel>("SelectPersonById", ht);
實際生成的SQL語句如下:
exec sp_executesql N'SELECT * FROM Person WHERE Id = @param0 AND Name = @param1',N'@param0 int,@param1 nvarchar(2)',@param0=1,@param1=N'劉備'
IBatis.Net還不錯哦,自動緩存參數化查詢的執行計划。
2、自定義參數類
自定義參數類通常是使用本實體類,當然你也可以自定義一個參數類(與SQL語句中的參數同名就可以)。
<select id="SelectPersonById" resultMap="Person" parameterClass="Ibatis.Net.Domain.PersonModel"> SELECT * FROM Person WHERE Id = #Id# AND Name = #Name# </select>
調用方法:
PersonModel p = new PersonModel(); p.Id = 1; p.Name = "劉備"; PersonModel p1 = mapper.QueryForObject<PersonModel>("SelectPersonById", p);
二、動態查詢
動態查詢的意思就是說,當滿足一定的條件,才拼接某一段SQL代碼。
還是用剛才的示例說明問題:
<select id="SelectPersonById" resultMap="Person" parameterClass="Hashtable" > SELECT TOP 1 * FROM Person WHERE 1=1 <dynamic prepend="AND"> <isLessEqual prepend="AND" property="Id" compareValue="3"> <!--當傳入的參數Id小於3時,才拼接該子句--> Id = #Id# </isLessEqual> <isNotEmpty prepend="AND" property="Name"> <!--當傳入的參數Name不為""或Null時,才拼接該子句--> Name = #Name# </isNotEmpty> </dynamic> </select>
調用的方法不變,有意思的地方在這里,假如傳入的參數為:ht.Add("Id",4);
則生成的SQL語句為:
SELECT TOP 1 * FROM Person WHERE 1=1
假如傳入的參數為:ht.Add("Id",2);
則生成的SQL語句為:
SELECT TOP 1 * FROM Person WHERE 1=1 AND Id = @param0',N'@param0 int',@param0=2
假如傳入的參數為:ht.Add("Id",2); ht.Add("Name","諸葛亮");
則生成的SQL語句為:
exec sp_executesql N'SELECT TOP 1 * FROM Person WHERE 1=1 AND Id = @param0 AND Name = @param1',N'@param0 int,@param1 nvarchar(3)',@param0=2,@param1=N'諸葛亮'
動態查詢就是這樣,根據一定的判斷條件,去判斷是否應該拼接某段SQL代碼。
更多的判斷條件如下:
屬性關鍵字 |
含義 |
<isEqual> |
如果參數相等於值則查詢條件有效。 |
<isNotEqual> |
如果參數不等於值則查詢條件有效。 |
<isGreaterThan> |
如果參數大於值則查詢條件有效。 |
<isGreaterEqual> |
如果參數大於等於值則查詢條件有效。 |
<isLessEqual> |
如果參數小於值則查詢條件有效。 |
<isPropertyAvailable> |
如果參數中有此屬性則查詢條件有效。 |
<isNotPropertyAvailable> |
如果參數中沒有此屬性則查詢條件有效。 |
<isNull> |
如果參數為NULL則查詢條件有效。 |
<isNotNull> |
如果參數不為NULL則查詢條件有效。 |
<isEmpty> |
如果參數為空則查詢條件有效。 |
<isNotEmpty> |
如果參數不為空則查詢條件有效。 |
<isParameterPresent> |
如果存在參數對象則查詢條件有效。 |
<isNotParameterPresent> |
如果不存在參數對象則查詢條件有效。 |
屬性說明:
- perpend——可被覆蓋的SQL語句組成部分,添加在語句的前面,該屬性為可選。
- property——是比較的屬性,該屬性為必選。
- compareProperty——另一個用於和前者比較的屬性(必選或選擇compareValue屬性)
- compareValue——用於比較的值(必選或選擇compareProperty屬性)
還有一個比較特別的判斷條件:iterate。這個東西用於循環生成多個SQL片段。
<select id="SelectPersonWithCountryName" resultMap="Person"> SELECT Person.Id,Person.Age,Person.Name,Country.CountryName FROM Person INNER JOIN Country ON Person.CountryId = Country.Id </select> <select id="SelectPersonById" resultMap="Person" parameterClass="Hashtable" > SELECT * FROM Person <dynamic prepend="WHERE"> <isNotNull prepend="And" property="NameList"> <!--遍歷NameList參數,對於每一個生成一個Name in NameList[i]--> Name in <iterate property="NameList" open="(" close=")" conjunction=","> #NameList[]# </iterate> </isNotNull> </dynamic> </select>
調用方法為:
List<string> ListStr = new List<string>(); ListStr.Add("劉備"); ListStr.Add("黃忠"); ListStr.Add("曹操"); Hashtable ht = new Hashtable(); ht.Add("NameList",ListStr); IList<PersonModel> ListP = mapper.QueryForList<PersonModel>("SelectPersonById", ht);
生成的SQL語句為:
exec sp_executesql N'SELECT * FROM Person WHERE Name in (@param0,@param1,@param2)',N'@param0 nvarchar(2),@param1 nvarchar(2),@param2 nvarchar(2)',@param0=N'劉備',@param1=N'黃忠',@param2=N'曹操'
Iterate的屬性:
- prepend——可被覆蓋的SQL語句組成部分,添加在語句的前面,該屬性為可選。
- property——類型為List的用於遍歷的元素屬性,該屬性為必選。
- open——整個遍歷內容體開始的字符串,用於定義括號,該屬性為可選。
- close ——整個遍歷內容體結束的字符串,用於定義括號,該屬性為可選。
- conjunction——每次遍歷內容之間的字符串,用於定義AND或OR,該屬性為可選。
最后附上好不容易才找到的1.62的源代碼 http://mybatisnet.googlecode.com/svn/tags/cs_release_1.6.2/