iBATIS.net获取运行时sql语句
【本文原創(chuàng),第一次離首頁如此之近。發(fā)在候選區(qū)攢攢rp,管理員看著不合適可以撤下。】
雖然只在iBatis的世界里小打小鬧匆匆數(shù)月,卻歷經(jīng)數(shù)次與領(lǐng)導(dǎo)和同事激辯,再通過不懈努力學(xué)習(xí)和開發(fā)積累,樓豬終于被它小巧而不失強大,穩(wěn)定而不失靈活所折服。作為80后頑固、偏執(zhí)和nc一族,樓豬一向保守認(rèn)為自己是美貌與智慧并存的。仗著天資聰慧,在之前的“iBatis.net直接執(zhí)行sql語句”里曾經(jīng)公然抱怨iBATIS對sql語句的直接查看灰常的不友好,調(diào)試不方便,排除錯誤非常考驗眼神,很重要的一條(甚至應(yīng)該算是樓豬一開始就討厭排斥iBatis的罪魁禍?zhǔn)?就是參數(shù)化的sql語句。但是也不能說獲取到的運行時sql語句一點用木有,至少我們還是可以看到sql語句的大致組裝情況的。說到這里,再對照標(biāo)題,您可能會認(rèn)為樓豬是要教大家怎么獲取運行時的sql語句。以樓豬一貫自戀臭美的作風(fēng),這次會這么膚淺么......
再給大家一次大膽猜測的機會......當(dāng)當(dāng)當(dāng)當(dāng),我kao,新年新氣象,大家變得更聰明了,一點驚喜和意外都木有,果然。好了,有沒有新意,看看樓豬的介紹再說吧:
一、常見iBatis.net獲取運行時sql語句方式
通常我們都是在一個公共類里寫一個方法,單獨作為獲取sql語句的幫助類(IBatisHelper.cs),然后在sqlmapper方法調(diào)用的地方調(diào)用幫助類和它的方法。
1、實現(xiàn)代碼
????????///?得到運行時ibatis.net動態(tài)生成的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語句出現(xiàn)異常:"?+?ex.Message;
????????????}
????????????return?result;
????????}
?2、使用幫助類獲取sql語句
接著采用類似如下實現(xiàn)方式進行調(diào)用:
????????{
????????????string?sql?=?IBatisHelper.GetRuntimeSql(this.SqlMapper,?this.GetStatementName("SelectPersons"),?model);
????????????return?this.SqlMapper.QueryForList<Person>(this.GetStatementName("SelectPersons"),?model);
????????}
在之前做過的大大小小形形色色的項目中,樓豬沒少這么寫,開發(fā)團隊其他成員也是一樣的,灰常和諧默契。
二、iBatis.net獲取運行時sql語句方式的改進 但是每做一個新項目就要寫個一模一樣的幫助類來(嗨,您現(xiàn)在嗅到壞味道并且看到杯具了吧?!),偏執(zhí)追求完美的nc樓豬就想,各位大神早就教導(dǎo)我們重復(fù)是邪惡的(Duplication is Evil (DIE)),大家一起不亦樂乎地重復(fù)呢?這里您一定會善意建議樓豬把幫助類寫進公共類庫里,大家以后公共調(diào)用那個類庫就可以了。思路確實沒錯,很不客氣地說,樓豬第一次使用iBatis就想這么干了。看到這里含蓄的您可能已經(jīng)會心一笑,豪放點的也許已經(jīng)也有“tmd,老子也和你想到一塊去了”之感。其實在很多技術(shù)問題上,大家的看法最終還是非常容易達到高度統(tǒng)一的。
樓豬是通過抽象出一個具有獲取運行時sql語句的方法的BaseIBatisDao基類,封裝并改進初始化SqlMapper對象的方式實現(xiàn)公共調(diào)用的:
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動態(tài)生成的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語句出現(xiàn)異常:"?+?ex.Message;
????????????}
????????????return?result;
????????}
????????///?<summary>
????????///?獲取sqlMap對應(yīng)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)通過單例模式實現(xiàn)的:
using?System;using?System.Collections.Generic;
using?IBatisNet.DataMapper;
using?IBatisNet.DataMapper.Configuration;
using?IBatisNet.DataMapper.SessionStore;
namespace?DotNet.Common.IBatisUtil
{
????///?<summary>
????///?SqlMap創(chuàng)建管理
????///?</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中調(diào)用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語句通常都是開發(fā)者調(diào)試時的一種輔助。調(diào)試成功后,您可以及時把獲取sql的那一行注釋掉。有了這個方法,普通開發(fā)調(diào)試就比較圓滿了(您還可以按照項目需要擴展出其他方法,比如通過datatable,datareader等等獲取sql語句),而且調(diào)用灰常省事。
3、關(guān)于DAL層的幾句廢話
a、在本文最下面,樓豬會給出demo下載鏈接。之前的幾篇介紹總結(jié)iBatis的文章里,iBatis的類庫版本較低(1.3.0.0),現(xiàn)在已經(jīng)升級到(1.6.1.0),開發(fā)環(huán)境Vs2008+Sql? Server2005 Express.在運行程序的時候,請先在Sql Server上執(zhí)行Script文件夾下的sql腳步建數(shù)據(jù)庫和對應(yīng)的表。要下載學(xué)習(xí)的童鞋請注意。
b、model層的說明
Person類直接繼承的第一個基類(BaseModel)存的是其他表也可能用到的公共字段(主鍵Id);BaseModel直接繼承自用于作為擴展查詢條件的BaseQuery類;BaseQuery類繼承自支持with方式分頁的PagerBase類。其實看命名您可以猜到它們的各自作用了。不同的實體類可以按需要繼承這三個類。
c、with分頁查詢方式
這個是sql server2005的with和公用表表達式提供的功能,分頁效率和效果都很不錯,dao所對應(yīng)的xml文件里用到了“iBATIS.net復(fù)用sql語句片段”功能。sql server2005前版本和非sql server的數(shù)據(jù)庫不支持此方式。樓豬之前都是通過更通用的二次top方式進行分頁,希望您留意。
最后ps,本來計劃在本文把iBatis事務(wù)和它的自帶分頁功能一并介紹的,一想起曾經(jīng)無比挫折的事務(wù)使用經(jīng)歷,興致全無。低俗的一句結(jié)束:日后再說。
demo下載:IBatisApp
http://www.cnblogs.com/jeffwongishandsome/archive/2010/02/24/1672960.html
總結(jié)
以上是生活随笔為你收集整理的iBATIS.net获取运行时sql语句的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 骨龄比实际年龄大是什么意思(骨龄比实际年
- 下一篇: ibatis动态查询条件