【本文原创,第一次离首页如此之近。发在候选区攒攒rp,管理员看着不合适可以撤下。】

  虽然只在iBatis的世界里小打小闹匆匆数月,却历经数次与领导和同事激辩,再通过不懈努力学习和开发积累,楼猪终于被它小巧而不失强大,稳定而不失灵活所折服。作为80后顽固、偏执和nc一族,楼猪一向保守认为自己是美貌与智慧并存的。仗着天资聪慧,在之前的“iBatis.net直接执行sql语句”里曾经公然抱怨iBATIS对sql语句的直接查看灰常的不友好,调试不方便,排除错误非常考验眼神,很重要的一条(甚至应该算是楼猪一开始就讨厌排斥iBatis的罪魁祸首)就是参数化的sql语句。但是也不能说获取到的运行时sql语句一点用木有,至少我们还是可以看到sql语句的大致组装情况的。说到这里,再对照标题,您可能会认为楼猪是要教大家怎么获取运行时的sql语句。以楼猪一贯自恋臭美的作风,这次会这么肤浅么......
  再给大家一次大胆猜测的机会......当当当当,我kao,新年新气象,大家变得更聪明了,一点惊喜和意外都木有,果然。好了,有没有新意,看看楼猪的介绍再说吧:

一、常见iBatis.net获取运行时sql语句方式
通常我们都是在一个公共类里写一个方法,单独作为获取sql语句的帮助类(IBatisHelper.cs),然后在sqlmapper方法调用的地方调用帮助类和它的方法。
1、实现代码


        /// <summary>
        /// 得到运行时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语句
接着采用类似如下实现方式进行调用:

       public IList<Person> SelectPersons(Person model)
        {
            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 System;
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语句的更多相关文章

  1. IBatis.Net获取执行的Sql语句

    前言 IBatis.Net中Sql语句是些在配置文件中的,而且配置文件是在程序启动时读取的(我们开发的时候需要将其设置成较新复制或者是始终复制),而不是程序将其包含在其中(例如NHibernate的映 ...

  2. Thinkphp5 获取执行的sql语句

    获取最后执行的sql语句 $str_order_action = db('order_action')->getLastSql(); //获取最后执行的sql语句 获取执行的sql语句 $ord ...

  3. kettle job如何利用java的反射机制获取执行的sql语句

    kettle job中的JavaScript如何获取同一个job中SQL步骤的执行语句并让执行语句记录在日志中呢?首先写日志需要用到job中JavaScript写日志的方法,其次是利用java反射机制 ...

  4. Ibatis 后台打印完整的sql语句

    http://blog.csdn.net/deng11342/article/details/9122015 http://www.blogjava.net/libin2722/archive/200 ...

  5. 常用的获取时间差的sql语句

    "select count(*) from [注册] where datediff(day,time,getdate())<1";//获取当天注册人员数 sql=" ...

  6. PHP获取MySQL执行sql语句的查询时间

    //计时开始 runtime(); //执行查询 mysql_query($sql); //计时结束. echo runtime(1); //计时函数 function runtime($mode=0 ...

  7. oracle常用运维sql语句

    1.查询dblink语句 col owner for a20col db_link for a30col username for a20col host for a30set linesize 12 ...

  8. Ibatis学习总结7--SqlMapClient 执行 SQL 语句

    SqlMapCient 类提供了执行所有 mapped statement 的 API.这些方法如下: public int insert(String statementName, Object p ...

  9. 后台代码对iBatis配置文件中具体的sql语句的调用实现(被封装的增删改查)

    using IBatisNet.Common.Exceptions; using IBatisNet.DataAccess; using IBatisNet.DataAccess.DaoSession ...

随机推荐

  1. Android源码分析之SparseArray

    本来接下来应该分析MessageQueue了,可是我这几天正好在实际开发中又再次用到了SparseArray(之前有用到过一次,那次只是 大概浏览了下源码,没做深入研究),于是在兴趣的推动下,花了些时 ...

  2. 通知中心NSNotificationCenter的使用

    通知中心NSNotificationCenter的使用 Cocoa框架中,通知中心以及KVO都属于设计模式中的观察者. Source 在使用通知中心之前,对通知中心类进行了简单的封装,以便可读性更强. ...

  3. 关于配置并发访问的服务器apache、nginx

    一. apache,nginx比较     关于Apache与Nginx的优势比较  (apache计算密集型   nginx io密集型  各有优势,不存在谁取代谁) 二.nginx 基于nginx ...

  4. Effective Java 07 Avoid finallizers

    NOTE Never do anything time-critical in a finalizer. Never depend on a finalizer to update critical ...

  5. javascript/jquery 常见功能实现(持续更新...)

    1. input 只能输入整数数字和字母 $(document).on('keyup','#no',function(){ var val = $.trim($(this).val()); if(va ...

  6. 问题解决——OpenGL超级宝典 关于gltDrawTorus的错误解决

    看OpenGL超级宝典的时候,遇到一个函数 “gltDrawTorus”,在TRANSFORM和SPHEREWORLD中都有用到.但是一开始在自己写示例代码里时却没法使用,而在作者的代码目录结构下却可 ...

  7. 基础总结篇之一:Activity生命周期

    子曰:溫故而知新,可以為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就完全掌握,那基本不大可能,所以我们需要经常回过头再仔细研读几遍,以领悟到作者的思想精 ...

  8. Lighttpd

    一.简介 Lighttpd 是一个德国人领导的开源Web服务器软件,其根本的目的是提供一个专门针对高性能网站,安全.快速.兼容性好并且灵活的web server环境.具有非常低的内存开销,cpu占用率 ...

  9. uva 1471 defence lines——yhx

    After the last war devastated your country, you - as the king of the land of Ardenia - decided it wa ...

  10. NOIP2008 普及组T1 ISBN号码 解题报告-S.B.S.

    题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一 ...