iBATIS.net获取运行时sql语句
【本文原创,第一次离首页如此之近。发在候选区攒攒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语句的更多相关文章
- IBatis.Net获取执行的Sql语句
前言 IBatis.Net中Sql语句是些在配置文件中的,而且配置文件是在程序启动时读取的(我们开发的时候需要将其设置成较新复制或者是始终复制),而不是程序将其包含在其中(例如NHibernate的映 ...
- Thinkphp5 获取执行的sql语句
获取最后执行的sql语句 $str_order_action = db('order_action')->getLastSql(); //获取最后执行的sql语句 获取执行的sql语句 $ord ...
- kettle job如何利用java的反射机制获取执行的sql语句
kettle job中的JavaScript如何获取同一个job中SQL步骤的执行语句并让执行语句记录在日志中呢?首先写日志需要用到job中JavaScript写日志的方法,其次是利用java反射机制 ...
- Ibatis 后台打印完整的sql语句
http://blog.csdn.net/deng11342/article/details/9122015 http://www.blogjava.net/libin2722/archive/200 ...
- 常用的获取时间差的sql语句
"select count(*) from [注册] where datediff(day,time,getdate())<1";//获取当天注册人员数 sql=" ...
- PHP获取MySQL执行sql语句的查询时间
//计时开始 runtime(); //执行查询 mysql_query($sql); //计时结束. echo runtime(1); //计时函数 function runtime($mode=0 ...
- oracle常用运维sql语句
1.查询dblink语句 col owner for a20col db_link for a30col username for a20col host for a30set linesize 12 ...
- Ibatis学习总结7--SqlMapClient 执行 SQL 语句
SqlMapCient 类提供了执行所有 mapped statement 的 API.这些方法如下: public int insert(String statementName, Object p ...
- 后台代码对iBatis配置文件中具体的sql语句的调用实现(被封装的增删改查)
using IBatisNet.Common.Exceptions; using IBatisNet.DataAccess; using IBatisNet.DataAccess.DaoSession ...
随机推荐
- setSupportActionBar(toolbar)导致程序崩溃闪退
最近在做一个项目,使用了第三方的开源项目,主要是想实现android5.0之后推出的MaterialDesign的风格,但是代码已经写好了,发现一运行就闪退,所以就开始debug,发现问题出现在 To ...
- App Icon生成工具(转载)
原地址:http://www.cocoachina.com/bbs/read.php?tid=290247 下载软件:在AppStore搜索App Icon Gear 打开软件 决定制作启动图或图标, ...
- virtualbox 中ubantu虚拟机范文win7文件夹
宿主机操作系统: windows7_x64 旗舰版 Oracle VM virtualBox版本:5.0.12 虚拟机操作系统: Ubantu15.12_x64 Desktop版本 让虚拟机可以访 ...
- ubuntu14.04下nodejs + npm + bower的安装、调试和部署
1. 简介 本文介绍ubuntu14.04下nodejs+npm+bower的安装.调试和部署 参考文档 https://docs.npmjs.com/getting-started https: ...
- BIEE从底层表结构向上更新
影响BIEE查询结果的几个因素: 1.数据库表结构变化后,RPD如何处理? 更新物理层 增加.删除.修改表名. 添加字段:右键点击连接池,点击导入元数据.勾掉关键字,重新导入那张表. 删除字段:直接右 ...
- QT添加程序图标及窗口图标
程序图标 材料准备 图标文件:*.ico文件,存放在源文件同一目录下,如"myapp.ico" 写入图标 向*.pro文件中,独立一行写入"RC_ICONS = *.ic ...
- 烂泥:kvm安装windows系统蓝屏
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 最近一直在学习有关KVM的知识,实验一直是在虚拟机VM中进行的.今天刚好公司有一台空闲的服务器,直接拿来安装centos.kvm等等,然后相关的配置. ...
- 烂泥: KVM虚拟机Linux系统增加硬盘
本文由秀依林枫提供友情赞助,首发于烂泥行天下. Linux虚拟机在使用过程中,硬盘空间不够使用.由于前期没有做LVM,所以只能手动添加新的硬盘. 给虚拟机添加硬盘有两种方法: 1.通过virsh at ...
- Android 滑动效果入门篇(一)—— ViewFlipper
ViewFilpper 是Android官方提供的一个View容器类,继承于ViewAnimator类,用于实现页面切换,也可以设定时间间隔,让它自动播放.又ViewAnimator继承至于Frame ...
- python strip() lstrip() rstrip() 使用方法
Python中的strip用于去除字符串的首尾字符串,同理,lstrip用于去除最左边的字符,rstrip用于去除最右边的字符. 这三个函数都可传入一个参数,指定要去除的首尾字符. 需要注意的是,传入 ...