【本文原创,第一次离首页如此之近。发在候选区攒攒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. 【读书笔记】iOS-KVC

    一,KVC即键/值编码. 二,KVC的基本调用包括-valueForKey:和-setValue:forKey:. 三,对于KVC,Cocoa自动放入和取出标量值.也就是说,当使用setValueFo ...

  2. 博客建议(Suggestions)

    I don't know if you will like the music. But I am sure there are some songs which are really wonderf ...

  3. SQLServer中登录名的用户名配置

    其实这个问题困扰我很久了. 今夏(13.7)实习的时候第一次接触sqlserver 当时是统一安排,按部就班的做就行. 那时候链接数据库用的id是sa. 后来自己做小程序时候举得不管什么都用sa登录好 ...

  4. git提交报错

    Error occurred computing Git commit diffsMissing unknown 0000000000000000000000000000000000000000 co ...

  5. Linux 环境变量的配置

    一. 环境变量相关的几个配置文件(针对bash): 1.  /etc/profile 系统环境变量配置文件:针对整个系统的所有用户生效,系统启动后用户第一次登陆时,此文件被执行,并从/etc/prof ...

  6. 《HeadFirst设计模式》读后感——对学习设计模式的一些想法

    最近看完了<HeadFirst设计模式>,GOF的<设计模式——可复用面向对象软件的基础>的创建型模式也读完了,经历了从一无所知到茅塞顿开再到充满迷惑的过程. 不得不说< ...

  7. 续Gulp使用入门三步压缩图片

    gulp 压缩图片 压缩 图片文件可降低文件大小,提高图片加载速度. 找到规律转换为 gulp 代码 规律 找到 images/ 目录下的所有文件,压缩它们,将压缩后的文件存放在 dist/image ...

  8. Less里css表达式的写法

    项目中用的grunt-contrib-less, 写了以下less代码 .mapfix{ position: fixed; top:10px; width: 430px; z-index: 100; ...

  9. Hibernate占位符?和:及JPA

    小结一下hibernate占位符. 1.最常见的?占位符. String hql = "select a from Apple a where a.color=? a.weight>? ...

  10. TC79

    /* INSERT INTO TC79(PatientID,AdmissionDate,DischargeDate,Cost) SELECT * FROM ( SELECT 709,TO_DATE(' ...