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的效果。

主要代码如下:

  1. public static IList QueryPageList(ISqlMapper sqlMap, String statementName, Object parameter, int offset, int limit)
  2. {
  3. IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
  4. if(!sqlMap.IsSessionStarted)
  5. {
  6. sqlMap.OpenConnection();
  7. }
  8. RequestScope request = statement.Statement.Sql.GetRequestScope(statement, parameter, sqlMap.LocalSession);
  9. request.PreparedStatement.PreparedSql = dialect.GetLimitString(request.PreparedStatement.PreparedSql, offset, limit);
  10. statement.PreparedCommand.Create(request, sqlMap.LocalSession, statement.Statement, parameter);
  11. return RunQueryForList(request, sqlMap.LocalSession, parameter, statement.Statement);
  12. }
  13.  
  14. public static IList<T> QueryPageList<T>(ISqlMapper sqlMap, String statementName, Object parameter, int offset, int limit)
  15. {
  16. IMappedStatement statement = sqlMap.GetMappedStatement(statementName);
  17. if(!sqlMap.IsSessionStarted)
  18. {
  19. sqlMap.OpenConnection();
  20. }
  21. RequestScope request = statement.Statement.Sql.GetRequestScope(statement, new Hashtable(), sqlMap.LocalSession);
  22. request.PreparedStatement.PreparedSql = dialect.GetLimitString(request.PreparedStatement.PreparedSql, offset, limit);
  23. statement.PreparedCommand.Create(request, sqlMap.LocalSession, statement.Statement, parameter);
  24. return (List<T>)RunQueryForList<T>(request, sqlMap.LocalSession, parameter, statement.Statement);
  25. }
  26.  
  27. private static IList RunQueryForList(RequestScope request, ISqlMapSession session, object parameterObject, IStatement _statement)
  28. {
  29. IList list = null;
  30. using(IDbCommand command = request.IDbCommand)
  31. {
  32. list = (_statement.ListClass == null)? (new ArrayList()):(_statement.CreateInstanceOfListClass());
  33. IDataReader reader = command.ExecuteReader();
  34. try
  35. {
  36. while(reader.Read())
  37. {
  38. object obj = ResultStrategyFactory.Get(_statement).Process(request, ref reader, null);
  39. if(obj != BaseStrategy.SKIP)
  40. {
  41. list.Add(obj);
  42. }
  43. }
  44. }
  45. catch
  46. {
  47. throw;
  48. }
  49. finally
  50. {
  51. reader.Close();
  52. reader.Dispose();
  53. }
  54. ExecutePostSelect(request);
  55. RetrieveOutputParameters(request, session, command, parameterObject);
  56. }
  57. return list;
  58. }
  59.  
  60. private static IList<T> RunQueryForList<T>(RequestScope request, ISqlMapSession session, object parameterObject, IStatement _statement)
  61. {
  62. IList<T> list = new List<T>();
  63. using(IDbCommand command = request.IDbCommand)
  64. {
  65. list = (_statement.ListClass == null) ? (new List<T>()) : (_statement.CreateInstanceOfGenericListClass<T>());
  66. IDataReader reader = command.ExecuteReader();
  67. try
  68. {
  69. while(reader.Read())
  70. {
  71. object obj = ResultStrategyFactory.Get(_statement).Process(request, ref reader, null);
  72. if(obj != BaseStrategy.SKIP)
  73. {
  74. list.Add((T)obj);
  75. }
  76. }
  77. }
  78. catch
  79. {
  80. throw;
  81. }
  82. finally
  83. {
  84. reader.Close();
  85. reader.Dispose();
  86. }
  87. ExecutePostSelect(request);
  88. RetrieveOutputParameters(request, session, command, parameterObject);
  89. }
  90. return list;
  91. }
  92.  
  93. private static void ExecutePostSelect(RequestScope request)
  94. {
  95. while(request.QueueSelect.Count > )
  96. {
  97. PostBindind postSelect = request.QueueSelect.Dequeue() as PostBindind;
  98. PostSelectStrategyFactory.Get(postSelect.Method).Execute(postSelect, request);
  99. }
  100. }
  101.  
  102. private static void RetrieveOutputParameters(RequestScope request, ISqlMapSession session, IDbCommand command, object result)
  103. {
  104. if(request.ParameterMap != null)
  105. {
  106. int count = request.ParameterMap.PropertiesList.Count;
  107. for(int i = ; i < count; i++)
  108. {
  109. IBatisNet.DataMapper.Configuration.ParameterMapping.ParameterProperty mapping = request.ParameterMap.GetProperty(i);
  110. if(mapping.Direction == ParameterDirection.Output ||
  111. mapping.Direction == ParameterDirection.InputOutput)
  112. {
  113. string parameterName = string.Empty;
  114. if(session.DataSource.DbProvider.UseParameterPrefixInParameter == false)
  115. {
  116. parameterName = mapping.ColumnName;
  117. }
  118. else
  119. {
  120. parameterName = session.DataSource.DbProvider.ParameterPrefix +
  121. mapping.ColumnName;
  122. }
  123.  
  124. if(mapping.TypeHandler == null) // Find the TypeHandler
  125. {
  126. lock(mapping)
  127. {
  128. if(mapping.TypeHandler == null)
  129. {
  130. Type propertyType = ObjectProbe.GetMemberTypeForGetter(result, mapping.PropertyName);
  131.  
  132. mapping.TypeHandler = request.DataExchangeFactory.TypeHandlerFactory.GetTypeHandler(propertyType);
  133. }
  134. }
  135. }
  136.  
  137. // Fix IBATISNET-239
  138. //"Normalize" System.DBNull parameters
  139. IDataParameter dataParameter = (IDataParameter)command.Parameters[parameterName];
  140. object dbValue = dataParameter.Value;
  141.  
  142. object value = null;
  143.  
  144. bool wasNull = (dbValue == DBNull.Value);
  145. if(wasNull)
  146. {
  147. if(mapping.HasNullValue)
  148. {
  149. value = mapping.TypeHandler.ValueOf(mapping.GetAccessor.MemberType, mapping.NullValue);
  150. }
  151. else
  152. {
  153. value = mapping.TypeHandler.NullValue;
  154. }
  155. }
  156. else
  157. {
  158. value = mapping.TypeHandler.GetDataBaseValue(dataParameter.Value, result.GetType());
  159. }
  160.  
  161. request.IsRowDataFound = request.IsRowDataFound || (value != null);
  162.  
  163. request.ParameterMap.SetOutputParameter(ref result, mapping, value);
  164. }
  165. }
  166. }
  167. }

其中的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分页的更多相关文章

  1. boot集成mybatis分页插件pagehelper

    导入依赖 <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter ...

  2. Spring Boot 2.x(十三):你不知道的PageHelper

    PageHelper 说起PageHelper,使用过Mybatis的朋友可能不是很陌生,作为一款国人开发的分页插件,它基本上满足了我们的日常需求.但是,我想去官方文档看看这个东西配合Spring B ...

  3. SpringBoot项目集成PageHelper使用

    SpringBoot项目集成PageHelper使用 一.开始 ​ 地址:https://github.com/pagehelper/Mybatis-PageHelper ​ 在spring boot ...

  4. Hibernate全套增删改查+分页

    1.创建一个web工程 2.导入jar包 3.创建Student表 4.创建实体类 package com.entity; public class Student { private Integer ...

  5. struts2+spring+hibernate 实现分页

    在这里要感谢下这位博友发表的博文 http://www.blogjava.net/rongxh7/archive/2008/11/29/243456.html 通过对他代码的阅读,从而自己实现了网页分 ...

  6. mybatis实战教程(mybatis in action)之七:实现mybatis分页

    上一篇文章里已经讲到了mybatis与spring MVC的集成,并且做了一个列表展示,显示出所有article 列表,但没有用到分页,在实际的项目中,分页是肯定需要的.而且是物理分页,不是内存分页. ...

  7. 【SSM 5】Mybatis分页插件的使用

    一.添加maven依赖项 <span style="font-family:KaiTi_GB2312;font-size:18px;"><dependency&g ...

  8. Mybatis + SpringMVC + Maven实现分页查询

    使用Mybatis + Maven + SpringMVC 运行时,突然被需要分页查询的功能给难住了 这里推荐采用的插件是PageHelper这个插件,使用起来十分方便.该插件支持以下数据库: Ora ...

  9. mybatis的分页插件使用方法

    1.下载所需要的jar包,如果使用maven可以在maven中添加依赖: 插件的实现原理: 如果你想使用本项目的jar包而不是直接引入类,你可以在这里下载各个版本的jar包(点击Download下的j ...

随机推荐

  1. webpack 的简单使用

    p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "Helvetica Neue"; color: #323333 } p. ...

  2. php 连接 mssql 常见的所有问题

    php连接mssql时 ntwdblib.dllPHP连接MSSQL配置和PHP代码演示 收藏 如果实现了PHP和MySQL链接了,PHP和MSSQL的链接其实很简单: 支持MSSQL的本地链接和远程 ...

  3. 打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器

    老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′ 言归正传.大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery ...

  4. 加载音频Audio

    var cameraAudio = new Audio(); cameraAudio.src = 'camera.wav'; // 设置音频对象的属性,预加载视频 var options_audio ...

  5. extjs学习之Ext.selection.CheckboxModel

    Ext.onReady( function() { var store=Ext.create('Ext.data.Store', { storeId:'simpsonsStore', fields:[ ...

  6. flask-admin章节五:wtforms FormField超级炫酷使用

    1. 概述 查看wtforms代码树fields目录的core.py,会发现在文件开头有这样的语句: __all__ = ( 'BooleanField', 'DecimalField', 'Date ...

  7. Linux多线程服务端编程一些总结

    能接触这本书是因为上一个项目是用c++开发基于Linux的消息服务器,公司没有使用第三方的网络库,卷起袖子就开撸了.个人因为从业经验较短,主 要负责的是业务方面的编码.本着兴趣自己找了这本书.拿到书就 ...

  8. (转)linux下cp目录时排除一个或者多个目录的实现方法

    原文链接:http://www.jb51.net/LINUXjishu/88971.html 说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录 ...

  9. 实验 2 用C语言编写简单程序

    #include<stdio.h> int main() { int x,y; printf("enter x:"); scanf("%d",&am ...

  10. WebView cookie 管理

    在Android应用程序中经常会加载一个WebView页,如果需要客户端向WebView传递信息,比如Cookie,也是可以的. 需要应用程序先将Cookie注入进去,打开该网页时,WebView会将 ...