实现IBatisNet的Dialect分页
Hibernate有其独有的Dialect,对不同的数据库实现sql的分页。
用过MyBatis for Java,它可以拦截SQL语句,通过Interceptor对原始的sql语句进行修改,也就是可以实现自定义Dialect,实现与Hibernate相同效果的分页Dialect。
可是最近搞了个IBatisNet+Spring.Net的框架,IBatisNet是ibatis for Java版本转移过来的。
它没有MyBatis新版本所增加的功能,而IBatisNet自带的分页是通过IDataReader实现的逻辑分页,虽说在局域网环境上,对内存和带宽的影响不是很大,但个人习惯上还是看着很恶心。
上网找了很多天的资料,并没有发现有相当的资料,也似乎没有人这样做过(或许是做了没有共享出来)。
但无意中发现有代码是可以获取到运行时的sql语句的,于是把IBatisNet源码中的实现重新搬出来,修改了一下,算是也能实现Dialect的效果。
主要代码如下:
- public static IList QueryPageList(ISqlMapper sqlMap, String statementName, Object parameter, int offset, int limit)
- {
- IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
- if(!sqlMap.IsSessionStarted)
- {
- sqlMap.OpenConnection();
- }
- RequestScope request = statement.Statement.Sql.GetRequestScope(statement, parameter, sqlMap.LocalSession);
- request.PreparedStatement.PreparedSql = dialect.GetLimitString(request.PreparedStatement.PreparedSql, offset, limit);
- statement.PreparedCommand.Create(request, sqlMap.LocalSession, statement.Statement, parameter);
- return RunQueryForList(request, sqlMap.LocalSession, parameter, statement.Statement);
- }
- public static IList<T> QueryPageList<T>(ISqlMapper sqlMap, String statementName, Object parameter, int offset, int limit)
- {
- IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
- if(!sqlMap.IsSessionStarted)
- {
- sqlMap.OpenConnection();
- }
- RequestScope request = statement.Statement.Sql.GetRequestScope(statement, new Hashtable(), sqlMap.LocalSession);
- request.PreparedStatement.PreparedSql = dialect.GetLimitString(request.PreparedStatement.PreparedSql, offset, limit);
- statement.PreparedCommand.Create(request, sqlMap.LocalSession, statement.Statement, parameter);
- return (List<T>)RunQueryForList<T>(request, sqlMap.LocalSession, parameter, statement.Statement);
- }
- private static IList RunQueryForList(RequestScope request, ISqlMapSession session, object parameterObject, IStatement _statement)
- {
- IList list = null;
- using(IDbCommand command = request.IDbCommand)
- {
- list = (_statement.ListClass == null)? (new ArrayList()):(_statement.CreateInstanceOfListClass());
- IDataReader reader = command.ExecuteReader();
- try
- {
- while(reader.Read())
- {
- object obj = ResultStrategyFactory.Get(_statement).Process(request, ref reader, null);
- if(obj != BaseStrategy.SKIP)
- {
- list.Add(obj);
- }
- }
- }
- catch
- {
- throw;
- }
- finally
- {
- reader.Close();
- reader.Dispose();
- }
- ExecutePostSelect(request);
- RetrieveOutputParameters(request, session, command, parameterObject);
- }
- return list;
- }
- private static IList<T> RunQueryForList<T>(RequestScope request, ISqlMapSession session, object parameterObject, IStatement _statement)
- {
- IList<T> list = new List<T>();
- using(IDbCommand command = request.IDbCommand)
- {
- list = (_statement.ListClass == null) ? (new List<T>()) : (_statement.CreateInstanceOfGenericListClass<T>());
- IDataReader reader = command.ExecuteReader();
- try
- {
- while(reader.Read())
- {
- object obj = ResultStrategyFactory.Get(_statement).Process(request, ref reader, null);
- if(obj != BaseStrategy.SKIP)
- {
- list.Add((T)obj);
- }
- }
- }
- catch
- {
- throw;
- }
- finally
- {
- reader.Close();
- reader.Dispose();
- }
- ExecutePostSelect(request);
- RetrieveOutputParameters(request, session, command, parameterObject);
- }
- return list;
- }
- private static void ExecutePostSelect(RequestScope request)
- {
- while(request.QueueSelect.Count > )
- {
- PostBindind postSelect = request.QueueSelect.Dequeue() as PostBindind;
- PostSelectStrategyFactory.Get(postSelect.Method).Execute(postSelect, request);
- }
- }
- private static void RetrieveOutputParameters(RequestScope request, ISqlMapSession session, IDbCommand command, object result)
- {
- if(request.ParameterMap != null)
- {
- int count = request.ParameterMap.PropertiesList.Count;
- for(int i = ; i < count; i++)
- {
- IBatisNet.DataMapper.Configuration.ParameterMapping.ParameterProperty mapping = request.ParameterMap.GetProperty(i);
- if(mapping.Direction == ParameterDirection.Output ||
- mapping.Direction == ParameterDirection.InputOutput)
- {
- string parameterName = string.Empty;
- if(session.DataSource.DbProvider.UseParameterPrefixInParameter == false)
- {
- parameterName = mapping.ColumnName;
- }
- else
- {
- parameterName = session.DataSource.DbProvider.ParameterPrefix +
- mapping.ColumnName;
- }
- if(mapping.TypeHandler == null) // Find the TypeHandler
- {
- lock(mapping)
- {
- if(mapping.TypeHandler == null)
- {
- Type propertyType = ObjectProbe.GetMemberTypeForGetter(result, mapping.PropertyName);
- mapping.TypeHandler = request.DataExchangeFactory.TypeHandlerFactory.GetTypeHandler(propertyType);
- }
- }
- }
- // Fix IBATISNET-239
- //"Normalize" System.DBNull parameters
- IDataParameter dataParameter = (IDataParameter)command.Parameters[parameterName];
- object dbValue = dataParameter.Value;
- object value = null;
- bool wasNull = (dbValue == DBNull.Value);
- if(wasNull)
- {
- if(mapping.HasNullValue)
- {
- value = mapping.TypeHandler.ValueOf(mapping.GetAccessor.MemberType, mapping.NullValue);
- }
- else
- {
- value = mapping.TypeHandler.NullValue;
- }
- }
- else
- {
- value = mapping.TypeHandler.GetDataBaseValue(dataParameter.Value, result.GetType());
- }
- request.IsRowDataFound = request.IsRowDataFound || (value != null);
- request.ParameterMap.SetOutputParameter(ref result, mapping, value);
- }
- }
- }
- }
其中的dialect.GetLimitString(),你们可以用接口的方式,定义针对不同数据库的分页sql,拼接为分页sql即可。
而ExecutePostSelect和RetrieveOutputParameters方法,则是从按源实现代码来调用的,因为无法调用其原始代码,所以自己重新实现了一部分。
最近有人说,这东西具体怎么用其实看不懂,或者直接获取例子中的svn吧,里面集成的是spring.net+ibatis.net
svn://svn.code.sf.net/p/dswork/code/DsWorkNet
项目中引用的dll位于:svn://svn.code.sf.net/p/dswork/code/LibNet
也有集成了基于.net framework 4.0的MVC4的demo
svn://svn.code.sf.net/p/dswork/code/DsDemo/DemoNet
这个项目的运行还需要同时运行web项目:svn://svn.code.sf.net/p/dswork/code/web
即同时运行两个项目,web和DemoNet,否则样式和js等会找不到路径,在IIS Express中配置一下即可,DemoNet中有说明文件
以上所有的项目,获取到本地路径后,建议全部置于同一目录下。否则自己更改dll的引用路径
实现IBatisNet的Dialect分页的更多相关文章
- boot集成mybatis分页插件pagehelper
导入依赖 <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter ...
- Spring Boot 2.x(十三):你不知道的PageHelper
PageHelper 说起PageHelper,使用过Mybatis的朋友可能不是很陌生,作为一款国人开发的分页插件,它基本上满足了我们的日常需求.但是,我想去官方文档看看这个东西配合Spring B ...
- SpringBoot项目集成PageHelper使用
SpringBoot项目集成PageHelper使用 一.开始 地址:https://github.com/pagehelper/Mybatis-PageHelper 在spring boot ...
- Hibernate全套增删改查+分页
1.创建一个web工程 2.导入jar包 3.创建Student表 4.创建实体类 package com.entity; public class Student { private Integer ...
- struts2+spring+hibernate 实现分页
在这里要感谢下这位博友发表的博文 http://www.blogjava.net/rongxh7/archive/2008/11/29/243456.html 通过对他代码的阅读,从而自己实现了网页分 ...
- mybatis实战教程(mybatis in action)之七:实现mybatis分页
上一篇文章里已经讲到了mybatis与spring MVC的集成,并且做了一个列表展示,显示出所有article 列表,但没有用到分页,在实际的项目中,分页是肯定需要的.而且是物理分页,不是内存分页. ...
- 【SSM 5】Mybatis分页插件的使用
一.添加maven依赖项 <span style="font-family:KaiTi_GB2312;font-size:18px;"><dependency&g ...
- Mybatis + SpringMVC + Maven实现分页查询
使用Mybatis + Maven + SpringMVC 运行时,突然被需要分页查询的功能给难住了 这里推荐采用的插件是PageHelper这个插件,使用起来十分方便.该插件支持以下数据库: Ora ...
- mybatis的分页插件使用方法
1.下载所需要的jar包,如果使用maven可以在maven中添加依赖: 插件的实现原理: 如果你想使用本项目的jar包而不是直接引入类,你可以在这里下载各个版本的jar包(点击Download下的j ...
随机推荐
- webpack 的简单使用
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Helvetica Neue"; color: #323333 } p. ...
- php 连接 mssql 常见的所有问题
php连接mssql时 ntwdblib.dllPHP连接MSSQL配置和PHP代码演示 收藏 如果实现了PHP和MySQL链接了,PHP和MSSQL的链接其实很简单: 支持MSSQL的本地链接和远程 ...
- 打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器
老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′ 言归正传.大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery ...
- 加载音频Audio
var cameraAudio = new Audio(); cameraAudio.src = 'camera.wav'; // 设置音频对象的属性,预加载视频 var options_audio ...
- extjs学习之Ext.selection.CheckboxModel
Ext.onReady( function() { var store=Ext.create('Ext.data.Store', { storeId:'simpsonsStore', fields:[ ...
- flask-admin章节五:wtforms FormField超级炫酷使用
1. 概述 查看wtforms代码树fields目录的core.py,会发现在文件开头有这样的语句: __all__ = ( 'BooleanField', 'DecimalField', 'Date ...
- Linux多线程服务端编程一些总结
能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...
- (转)linux下cp目录时排除一个或者多个目录的实现方法
原文链接:http://www.jb51.net/LINUXjishu/88971.html 说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录 ...
- 实验 2 用C语言编写简单程序
#include<stdio.h> int main() { int x,y; printf("enter x:"); scanf("%d",&am ...
- WebView cookie 管理
在Android应用程序中经常会加载一个WebView页,如果需要客户端向WebView传递信息,比如Cookie,也是可以的. 需要应用程序先将Cookie注入进去,打开该网页时,WebView会将 ...