- 浏览: 670152 次
- 性别:
- 来自: 珠海
文章分类
最新评论
-
qq826928141:
longxing898 写道请教:使用jtds连接sql 20 ...
rapid-framework v3.9新版本发布 -
qq826928141:
美味人间 写道大哥,这个代码生成器怎么无法获取表和列的备注信息 ...
rapid-framework v3.9新版本发布 -
walle1027:
能发一下的测试代码吗?
rabbitmq性能测试 -
在世界的中心呼喚愛:
好东西,我就是参考这个!!!
iBatis3基于方言(Dialect)的分页 -
暂不存在:
怎么将{key}中的值替换掉
rapid系列:发布一款动态构造sql的工具: XsqlBuilder
(注:以下代码是基于ibatis3 beta4的扩展,ibatis3正式版如果实现改变,将会继续跟进修改)
iBatis3默认使用的分页是基于游标的分页,而这种分页在不同的数据库上性能差异不一致,最好的办法当然是使用类似hibernate的基于方言(Dialect)的物理分页功能。
iBatis3现在提供插件功能,通过插件我们可以编写自己的拦截器来拦截iBatis3的主要执行方法来完成相关功能的扩展。
能够拦截的的类如下:
Executor (update,query,flushStatements,commit,rollback,getTransaction,close,isClosed) ParameterHandler (getParameterObject,setParameters) ResultSetHandler (handleResultSets,handleOutputParameters) StatementHandler (prepare,parameterize,batch,update,query)
但此次我们感兴趣的是Executor.query()方法,查询方法最终都是执行该方法。
该方法完整是:
Executor.query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
分页方言的基本实现:
以Mysql数据库示例,即有一个方法 query(sql,offset,limit);
query("select * from user",5,10);
经过我们的拦截器拦截处理,变成
query("select * from user limit 5,10",0,0);
1.拦截类实现:
@Intercepts({@Signature( type= Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) public class OffsetLimitInterceptor implements Interceptor{ static int MAPPED_STATEMENT_INDEX = 0; static int PARAMETER_INDEX = 1; static int ROWBOUNDS_INDEX = 2; static int RESULT_HANDLER_INDEX = 3; Dialect dialect; public Object intercept(Invocation invocation) throws Throwable { processIntercept(invocation.getArgs()); return invocation.proceed(); } void processIntercept(final Object[] queryArgs) { //queryArgs = query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) MappedStatement ms = (MappedStatement)queryArgs[MAPPED_STATEMENT_INDEX]; Object parameter = queryArgs[PARAMETER_INDEX]; final RowBounds rowBounds = (RowBounds)queryArgs[ROWBOUNDS_INDEX]; int offset = rowBounds.getOffset(); int limit = rowBounds.getLimit(); if(dialect.supportsLimit() && (offset != RowBounds.NO_ROW_OFFSET || limit != RowBounds.NO_ROW_LIMIT)) { BoundSql boundSql = ms.getBoundSql(parameter); String sql = boundSql.getSql().trim(); if (dialect.supportsLimitOffset()) { sql = dialect.getLimitString(sql, offset, limit); offset = RowBounds.NO_ROW_OFFSET; } else { sql = dialect.getLimitString(sql, 0, limit); } limit = RowBounds.NO_ROW_LIMIT; queryArgs[ROWBOUNDS_INDEX] = new RowBounds(offset,limit); BoundSql newBoundSql = new BoundSql(sql, boundSql.getParameterMappings(), boundSql.getParameterObject()); MappedStatement newMs = copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql)); queryArgs[MAPPED_STATEMENT_INDEX] = newMs; } } private MappedStatement copyFromMappedStatement(MappedStatement ms,SqlSource newSqlSource) { Builder builder = new MappedStatement.Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType()); builder.resource(ms.getResource()); builder.fetchSize(ms.getFetchSize()); builder.statementType(ms.getStatementType()); builder.keyGenerator(ms.getKeyGenerator()); builder.keyProperty(ms.getKeyProperty()); builder.timeout(ms.getTimeout()); builder.parameterMap(ms.getParameterMap()); builder.resultMaps(ms.getResultMaps()); builder.cache(ms.getCache()); MappedStatement newMs = builder.build(); return newMs; } public Object plugin(Object target) { return Plugin.wrap(target, this); } public void setProperties(Properties properties) { String dialectClass = new PropertiesHelper(properties).getRequiredString("dialectClass"); try { dialect = (Dialect)Class.forName(dialectClass).newInstance(); } catch (Exception e) { throw new RuntimeException("cannot create dialect instance by dialectClass:"+dialectClass,e); } System.out.println(OffsetLimitInterceptor.class.getSimpleName()+".dialect="+dialectClass); } public static class BoundSqlSqlSource implements SqlSource { BoundSql boundSql; public BoundSqlSqlSource(BoundSql boundSql) { this.boundSql = boundSql; } public BoundSql getBoundSql(Object parameterObject) { return boundSql; } } }
2.ibatis3配置文件内容:
<configuration> <plugins> <!-- 指定数据库分页方言Dialect, 其它方言:OracleDialect,SQLServerDialect,SybaseDialect,DB2Dialect,PostgreSQLDialect,MySQLDialect,DerbyDialect--> <plugin interceptor="cn.org.rapid_framework.ibatis3.plugin.OffsetLimitInterceptor"> <property name="dialectClass" value="cn.org.rapid_framework.jdbc.dialect.MySQLDialect"/> </plugin> </plugins> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/company/project/model/mapper/BlogMapper.xml" /> </mappers> </configuration>
3.MysqlDialect实现
public class MySQLDialect extends Dialect{ public boolean supportsLimitOffset(){ return true; } public boolean supportsLimit() { return true; } public String getLimitString(String sql, int offset, int limit) { return getLimitString(sql,offset,String.valueOf(offset),limit,String.valueOf(limit)); } public String getLimitString(String sql, int offset,String offsetPlaceholder, int limit, String limitPlaceholder) { if (offset > 0) { return sql + " limit "+offsetPlaceholder+","+limitPlaceholder; } else { return sql + " limit "+limitPlaceholder; } } }
其它数据库的Dialect实现请查看:
4.分页使用
直接调用SqlSession.selectList(statement, parameter, new RowBounds(offset,limit))即可使用物理分页
5.存在的问题
现不是使用占位符的方式(即不是“limit ?,?”而是使用“limit 8,20”)使用分页
完整代码可以查看即将发布的rapid-framework 3.0的ibatis3插件
评论
11 楼
在世界的中心呼喚愛
2015-12-07
好东西,我就是参考这个!!!
10 楼
王星游
2011-09-01
谢谢,很有用。我用mybatis generator生成了大量pojo,example对象和xml文件,在楼主这种拦截器的方式下,都不用再更改了,要不然我还得去手动去每一个xml里自己添加limit条件。
不过在DAO层我也不能在简单的这样写了:
List<User> userList=userMapper.selectByExample(new UserExample());
只能采用mybatis-spring-3.0的线程安全的SqlSessionTemplate:
sqlSessionTemplate.selectList("com.watchzerg.persistence.UserMapper.selectByExample", new UserExample(), new RowBounds(0,10));
不过在DAO层我也不能在简单的这样写了:
List<User> userList=userMapper.selectByExample(new UserExample());
只能采用mybatis-spring-3.0的线程安全的SqlSessionTemplate:
sqlSessionTemplate.selectList("com.watchzerg.persistence.UserMapper.selectByExample", new UserExample(), new RowBounds(0,10));
9 楼
zhouhe
2011-07-04
Cause: java.sql.SQLException: ORA-01008: 并非所有变量都已绑定。
我试了一下,报错了,不知道我的代码有啥问题。
如果在Eclipse中Debug,把SQL中的分页参数“问号”换成数字,就好使了。
我漏掉什么步骤了?
指点一下吧。
我试了一下,报错了,不知道我的代码有啥问题。
如果在Eclipse中Debug,把SQL中的分页参数“问号”换成数字,就好使了。
我漏掉什么步骤了?
指点一下吧。
8 楼
zhouhe
2011-07-04
Cause: java.sql.SQLException: ORA-01008: 并非所有变量都已绑定。
7 楼
zhouhe
2011-07-04
我试了一下,报错了,不知道我的代码有啥问题。
6 楼
liuwei_blog
2011-03-02
赞
5 楼
badqiu
2010-04-30
不一定吧, 你可以写两个ibatis configation.xml吧,因为如果是不同数据库的,肯定也存在两个数据源的.
4 楼
cameron8
2010-04-26
并且重新写个xml文件也没有用,这种做法只能用单一的数据库.
3 楼
cameron8
2010-04-26
<plugin interceptor="cn.org.rapid_framework.ibatis3.plugin.OffsetLimitInterceptor"> <property name="dialectClass" value="cn.org.rapid_framework.jdbc.dialect.MySQLDialect"/>
不能同时支持两种数据库Dialect,
因为dialectClass属性加载的时候会复盖
2 楼
pochonlee
2009-10-20
3.0顶一个!期待更多。
1 楼
超级潜水员
2009-10-19
支持lz的3.0喔!!!
发表评论
-
rapid-framework v3.9新版本发布
2010-07-13 21:17 13427hi,all 本次新版本发布最主要的更新内容 ... -
为velocity,freemarker提供jsp:include功能
2010-06-13 19:26 11420一.介绍 使用JSP的都知道jsp:include指令,可以 ... -
rapid-framework发布新版本: v3.5
2010-03-23 19:01 4472本次的主要更新内容是重新拾起flex,重整了flex插件. 而 ... -
扩展freemarker,velocity,实现模板的管道操作
2010-01-12 20:54 4608操作系统中有一个很重要的功能,就是可以使用管道,即将前一个应用 ... -
扩展Velocity,实现模板的继承
2009-12-28 12:00 5502与我之前的扩展freemarker类似,现新增加三个指令:bl ... -
扩展freemarker,实现模板的继承
2009-12-22 10:11 9212现扩展freemarker,新增加三个指令: @ ... -
spring REST中的内容协商(同一资源,多种展现:xml,json,html)
2009-12-21 14:14 21730接上一篇对spring rest的描述. ... -
在jsp中实现"类"的继承关系
2009-12-09 17:59 72371.介绍 使用过python django模板 ... -
rapid-framework发布v3.0 版本
2009-11-11 09:46 4919虽然spring 3.0及ibatis3还未发布,但rap ... -
与Spring BlazeDS Integration相比,更简单的实现来调用spring bean
2009-10-12 11:15 4096注:后面使用SBI替代Spring BlazeDS In ... -
rapid-framework发布v2.5.0版本
2009-09-21 09:54 2259赶在国庆之前发布一个版本,庆祝国庆,:) 更新内 ... -
rapid-framework工具类介绍一: 异步IO类
2009-05-08 01:16 2208在一些特殊的场合,我们可能需要使用异步的IO来大幅提高性能. ... -
rapid-validation发布v1.5版本
2008-12-09 11:44 8173在线演示:http://www.rapid-framework ... -
rapid-framework v2.x路线图
2008-09-09 20:43 2677在1.0.2发布以后,很多同学认为切换至struts2 ... -
rapid-framework v1.0.x带控制条的演示视频放出
2008-08-20 13:28 2003很多同学报怨rapid-framework的演示视频太快,现在 ... -
rapid-framework发布v1.0.2版本
2008-08-13 11:39 2658该版本主要增加的相关文档导航,及一些模板及目录的调整 在线文档 ... -
动态构造sql利器:rapid-xsqlbuider 详细说明
2008-08-06 09:07 5014特性列表: 动态构造sql条件语句,提供sql拼接与使用占 ... -
很高兴大家下载rapid-framework
2008-08-04 11:42 7167看到有很多人下载,心情蛮爽的,这个就是做开源最高兴的吧. 大家 ... -
正式发布类似rails的框架:rapid-framework,文档补充中...
2008-07-29 09:11 5110基于spring,struts(struts2),hibe ... -
最适合实际开发需要的:<代码生成器>发布:rapid-generator-v1.0
2008-07-22 09:05 4263现阶段内置模板可以生成的包括: 可以生成java的hibern ...
相关推荐
ibatis调用oracle存储过程分页
ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件ibatis_likehbm高效分页组件 ibatis_likehbm高效分页组件 ibatis_likehbm...
NULL 博文链接:https://tianke645.iteye.com/blog/876116
通过修改ibatis源码实现sql分页。由于ibatis默认分页是全部查出,然后再从中取出相应的数据实现分页,效率底。所以需要扩展
ibatis 物理分页jar ,与官方ibatis不冲突,可直接使用。
底层 到 页面展示 , dao层 service层 action层 到tld 到jsp都是、已经写好 你只要调用就可以。非常好用的jsp分页标签(如果不明白的地方,可以私聊我)
公司的大部分项目都开始使用IBatis作为O/R Mapping了,但是在使用的过程中也发现了很多不方便和存在争议的地方,其中一个不方便的地方就是分页,目前的处理方式都是在sqlMap中写针对特定数据库的物理分页Sql语句,对于...
Ibatis 2.3.4 数据库无关分页 有示例,可以运行 网上找的很不错
Struts2-spring-ibatis 整合及存储过程分页.
struts2+spring+ibatis+oracle+分页搜索+上传附件实例!完整版!
Ibatis SQLServerDialect 2008 分页 可实现SQLServerDialect 分页 支持ibatis3
ibatis实现分页技术,其中的分页都已经封装好了,大家需要的话可以下载下来看下
Ibatis3,手册,Ibatis3手册,Ibatis3使用手册,Ibatis3参考手册
Ibatis .net 分页 查询, 可以参考下, Ibatis .net 分页 查询
小弟新手,第一次发自己的项目,整合了ssi,实现了ibatis连接oracle的分页,这个分页没有网上说的那么复杂,只是拼了sql分页语句就可以了
ssi_struts2_spring_ibatis oracle数据库.增删改查分页 示例.有简单页面.好资料.!
spring+ibatis+oracle分页缓存源码
NULL 博文链接:https://sarin.iteye.com/blog/1026061
ibatis struts2 spring3 mybatis 分页 crud 完整代码
一直以来ibatis的分页都是通过滚动ResultSet实现的,应该算是逻辑分页吧。逻辑分页虽然能很干净地独立于特定数据库,但效率在多数情况下不及特定数据库支持的物理分页,而hibernate的分页则是直接组装sql,充分利用...