iBATIS.net获取运行时sql语句
【本文原創,第一次離首頁如此之近。發在候選區攢攢rp,管理員看著不合適可以撤下?!?br /> 雖然只在iBatis的世界里小打小鬧匆匆數月,卻歷經數次與領導和同事激辯,再通過不懈努力學習和開發積累,樓豬終于被它小巧而不失強大,穩定而不失靈活所折服。作為80后頑固、偏執和nc一族,樓豬一向保守認為自己是美貌與智慧并存的。仗著天資聰慧,在之前的“iBatis.net直接執行sql語句”里曾經公然抱怨iBATIS對sql語句的直接查看灰常的不友好,調試不方便,排除錯誤非常考驗眼神,很重要的一條(甚至應該算是樓豬一開始就討厭排斥iBatis的罪魁禍首)就是參數化的sql語句。但是也不能說獲取到的運行時sql語句一點用木有,至少我們還是可以看到sql語句的大致組裝情況的。說到這里,再對照標題,您可能會認為樓豬是要教大家怎么獲取運行時的sql語句。以樓豬一貫自戀臭美的作風,這次會這么膚淺么......
再給大家一次大膽猜測的機會......當當當當,我kao,新年新氣象,大家變得更聰明了,一點驚喜和意外都木有,果然。好了,有沒有新意,看看樓豬的介紹再說吧:
一、常見iBatis.net獲取運行時sql語句方式
通常我們都是在一個公共類里寫一個方法,單獨作為獲取sql語句的幫助類(IBatisHelper.cs),然后在sqlmapper方法調用的地方調用幫助類和它的方法。
1、實現代碼
????????///?得到運行時ibatis.net動態生成的SQL
????????///?</summary>
????????///?<param?name="sqlMapper"></param>
????????///?<param?name="statementName"></param>
????????///?<param?name="paramObject"></param>
????????///?<returns></returns>
????????public static?string?GetRuntimeSql(ISqlMapper?sqlMapper,?string?statementName,?object?paramObject)
????????{
????????????string?result?=?string.Empty;
????????????try
????????????{
????????????????IMappedStatement?statement?=?sqlMapper.GetMappedStatement(statementName);
????????????????if?(!sqlMapper.IsSessionStarted)
????????????????{
????????????????????sqlMapper.OpenConnection();
????????????????}
????????????????RequestScope?scope?=?statement.Statement.Sql.GetRequestScope(statement,?paramObject,?sqlMapper.LocalSession);
????????????????result?=?scope.PreparedStatement.PreparedSql;
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????result?=?"獲取SQL語句出現異常:"?+?ex.Message;
????????????}
????????????return?result;
????????}
?2、使用幫助類獲取sql語句
接著采用類似如下實現方式進行調用:
????????{
????????????string?sql?=?IBatisHelper.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("SelectPersons"),?model);
????????????return?this.SqlMapper.QueryForList<Person>(this.GetStatementName("SelectPersons"),?model);
????????}
在之前做過的大大小小形形色色的項目中,樓豬沒少這么寫,開發團隊其他成員也是一樣的,灰常和諧默契。
二、iBatis.net獲取運行時sql語句方式的改進 但是每做一個新項目就要寫個一模一樣的幫助類來(嗨,您現在嗅到壞味道并且看到杯具了吧?!),偏執追求完美的nc樓豬就想,各位大神早就教導我們重復是邪惡的(Duplication is Evil (DIE)),大家一起不亦樂乎地重復呢?這里您一定會善意建議樓豬把幫助類寫進公共類庫里,大家以后公共調用那個類庫就可以了。思路確實沒錯,很不客氣地說,樓豬第一次使用iBatis就想這么干了。看到這里含蓄的您可能已經會心一笑,豪放點的也許已經也有“tmd,老子也和你想到一塊去了”之感。其實在很多技術問題上,大家的看法最終還是非常容易達到高度統一的。
樓豬是通過抽象出一個具有獲取運行時sql語句的方法的BaseIBatisDao基類,封裝并改進初始化SqlMapper對象的方式實現公共調用的:
1、BaseIBatisDao泛型抽象類
using?IBatisNet.DataMapper;
using?IBatisNet.DataMapper.Scope;
using?IBatisNet.DataMapper.MappedStatements;
namespace?DotNet.Common.IBatisUtil
{
????public?abstract?class?BaseIBatisDao<T>?where?T?:?class
????{
????????#region?Properties
????????public?ISqlMapper?SqlMapper?{?get;?set;?}
????????#endregion
????????#region?Constructor
????????public?BaseIBatisDao()
????????{
????????}
????????public?BaseIBatisDao(string?mapperName)
????????{
????????????this.SqlMapper?=?SqlMapperManager.GetMapper(mapperName);
????????}
????????#endregion
????????#region?Functions
????????///?<summary>
????????///?得到運行時ibatis.net動態生成的SQL
????????///?</summary>
????????///?<param?name="sqlMapper"></param>
????????///?<param?name="statementName"></param>
????????///?<param?name="paramObject"></param>
????????///?<returns></returns>
????????public?virtual?string?GetRuntimeSql(ISqlMapper?sqlMapper,?string?statementName,?object?paramObject)
????????{
????????????string?result?=?string.Empty;
????????????try
????????????{
????????????????IMappedStatement?statement?=?sqlMapper.GetMappedStatement(statementName);
????????????????if?(!sqlMapper.IsSessionStarted)
????????????????{
????????????????????sqlMapper.OpenConnection();
????????????????}
????????????????RequestScope?scope?=?statement.Statement.Sql.GetRequestScope(statement,?paramObject,?sqlMapper.LocalSession);
????????????????result?=?scope.PreparedStatement.PreparedSql;
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????result?=?"獲取SQL語句出現異常:"?+?ex.Message;
????????????}
????????????return?result;
????????}
????????///?<summary>
????????///?獲取sqlMap對應statement的完整id
????????///?</summary>
????????///?<param?name="name"></param>
????????///?<returns></returns>
????????protected?virtual?string?GetStatementName(string?name)
????????{
????????????return?string.Format("{0}.{1}",?typeof(T).Namespace,?name);
????????}
????????#endregion
????}
}
?在這個基類中,在初始化SqlMapper對象的地方,樓豬是通過一個輔助類(SqlMapperManager)通過單例模式實現的:
using?System;using?System.Collections.Generic;
using?IBatisNet.DataMapper;
using?IBatisNet.DataMapper.Configuration;
using?IBatisNet.DataMapper.SessionStore;
namespace?DotNet.Common.IBatisUtil
{
????///?<summary>
????///?SqlMap創建管理
????///?</summary>
????public?class?SqlMapperManager
????{
????????private?static?readonly?object?objSync?=?new?object();
????????private?static?readonly?IDictionary<string,?ISqlMapper>?dictMappers?=?null;
????????static?SqlMapperManager()
????????{
????????????dictMappers?=?new?Dictionary<string,?ISqlMapper>();
????????}
????????///?<summary>
????????///?實例化SqlMap對象
????????///?</summary>
????????///?<param?name="mapperName">通常.config文件</param>
????????///?<returns></returns>
????????public?static?ISqlMapper?GetMapper(string?mapperName)
????????{
????????????if?(string.IsNullOrEmpty(mapperName))
????????????{
????????????????throw?new?Exception("MapperName為空!");
????????????}
????????????if?(mapperName.ToLower().LastIndexOf(".config")?==?-1)
????????????{
????????????????mapperName?+=?".config";
????????????}
????????????ISqlMapper?mapper?=?null;
????????????if?(dictMappers.ContainsKey(mapperName))
????????????{
????????????????mapper?=?dictMappers[mapperName];
????????????}
????????????else
????????????{
????????????????if?(mapper?==?null)
????????????????{
????????????????????lock?(objSync)
????????????????????{
????????????????????????if?(mapper?==?null)
????????????????????????{
????????????????????????????mapper?=?new?DomSqlMapBuilder().Configure(mapperName);
????????????????????????????mapper.SessionStore?=?new?HybridWebThreadSessionStore(mapper.Id);
????????????????????????????dictMappers.Add(mapperName,?mapper);
????????????????????????}
????????????????????}
????????????????}
????????????}
????????????return?mapper;
????????}
????}
}
?2、在DAO中調用BaseIBatisDao基類
using?System.Collections.Generic;using?DotNet.Common.IBatisUtil;
using?IBatisNetApp.DAL.Model;
namespace?IBatisNetApp.DAL.DAO
{
????public?class?PersonDao?:?BaseIBatisDao<Person>
????{
????????public?PersonDao()
????????????:?base("Query.config")
????????{
????????}
????????public?IList<Person>?SelectPersons(Person?model)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("SelectPersons"),?model);
????????????return?this.SqlMapper.QueryForList<Person>(this.GetStatementName("SelectPersons"),?model);
????????}
????????public?IDictionary<int,?Person>?SelectDictStoreInfo(Person?model)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("SelectPersons"),?model);
????????????return?this.SqlMapper.QueryForDictionary<int,?Person>(this.GetStatementName("SelectPersons"),?model,?"Id");
????????}
????????public?IList<Person>?SelectPagerPersons(Person?model)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("SelectPagerPersons"),?model);
????????????return?this.SqlMapper.QueryForList<Person>(this.GetStatementName("SelectPagerPersons"),?model);
????????}
????????public?int?InsertPerson(Person?model)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("InsertPerson"),?model);
????????????int?result?=?0;
????????????object?obj?=?this.SqlMapper.Insert(this.GetStatementName("InsertPerson"),?model);
????????????if?(obj?!=?null)
????????????{
????????????????result?=?int.Parse(obj.ToString());
????????????}
????????????return?result;
????????}
????????public?int?DeletePersonById(int?id)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("DeletePersonById"),?id);
????????????int?result?=?0;
????????????object?obj?=?this.SqlMapper.Delete(this.GetStatementName("DeletePersonById"),?id);
????????????if?(obj?!=?null)
????????????{
????????????????result?=?int.Parse(obj.ToString());
????????????}
????????????return?result;
????????}
????????public?int?UpdatePersonById(Person?model)
????????{
????????????string?sql?=?this.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("UpdatePersonById"),?model);
????????????int?result?=?0;
????????????object?obj?=?this.SqlMapper.Update(this.GetStatementName("UpdatePersonById"),?model);
????????????if?(obj?!=?null)
????????????{
????????????????result?=?int.Parse(obj.ToString());
????????????}
????????????return?result;
????????}
????}
}
?如您所看到的那樣,在每一個方法里,我們要獲取運行時sql語句,只要用this來get一下就可以了,看上去這個方法就像是ibatis直接封裝好提供給我們的一樣,再對照之前的方式,強弱懸殊,高下立判。這里要特別說明,獲取運行時sql語句通常都是開發者調試時的一種輔助。調試成功后,您可以及時把獲取sql的那一行注釋掉。有了這個方法,普通開發調試就比較圓滿了(您還可以按照項目需要擴展出其他方法,比如通過datatable,datareader等等獲取sql語句),而且調用灰常省事。
3、關于DAL層的幾句廢話
a、在本文最下面,樓豬會給出demo下載鏈接。之前的幾篇介紹總結iBatis的文章里,iBatis的類庫版本較低(1.3.0.0),現在已經升級到(1.6.1.0),開發環境Vs2008+Sql? Server2005 Express.在運行程序的時候,請先在Sql Server上執行Script文件夾下的sql腳步建數據庫和對應的表。要下載學習的童鞋請注意。
b、model層的說明
Person類直接繼承的第一個基類(BaseModel)存的是其他表也可能用到的公共字段(主鍵Id);BaseModel直接繼承自用于作為擴展查詢條件的BaseQuery類;BaseQuery類繼承自支持with方式分頁的PagerBase類。其實看命名您可以猜到它們的各自作用了。不同的實體類可以按需要繼承這三個類。
c、with分頁查詢方式
這個是sql server2005的with和公用表表達式提供的功能,分頁效率和效果都很不錯,dao所對應的xml文件里用到了“iBATIS.net復用sql語句片段”功能。sql server2005前版本和非sql server的數據庫不支持此方式。樓豬之前都是通過更通用的二次top方式進行分頁,希望您留意。
最后ps,本來計劃在本文把iBatis事務和它的自帶分頁功能一并介紹的,一想起曾經無比挫折的事務使用經歷,興致全無。低俗的一句結束:日后再說。
demo下載:IBatisApp
http://www.cnblogs.com/jeffwongishandsome/archive/2010/02/24/1672960.html
總結
以上是生活随笔為你收集整理的iBATIS.net获取运行时sql语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 骨龄比实际年龄大是什么意思(骨龄比实际年
- 下一篇: ibatis动态查询条件