新的MyBatis比老的Ibatis有了个新的东东Plugin,在配置文件中
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<plugins>
<plugin interceptor="store.MySqlPaginationPlugin"/>
</plugins>
</configuration>
有了这个插件设计,就不用在那么麻烦的按照老的Ibatis的方式设计分页了,只需按照MyBatis要求的插件方式来拦截sql修改成分页形式了
先弄个基类,共享代码,支持所有的数据库,将不同的东西分离出来
Intercepts({@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public abstract class PaginationBasePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
Object[] queryArgs = invocation.getArgs();
MappedStatement ms = (MappedStatement) queryArgs[0];
BoundSql boundSql = ms.getBoundSql(queryArgs[1]);
String sql = boundSql.getSql().trim();
Object args = queryArgs[1];
sql = paginationSql(sql,args); //通过子类实现
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
MappedStatement newMs = copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));
queryArgs[0] = newMs;
return invocation.proceed();
}
protected abstract String paginationSql(String sql,Object args); //子类实现
//see: MapperBuilderAssistant
private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
MappedStatement.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());
//setStatementTimeout()
builder.timeout(ms.getTimeout());
//setStatementResultMap()
builder.parameterMap(ms.getParameterMap());
//setStatementResultMap()
builder.resultMaps(ms.getResultMaps());
builder.resultSetType(ms.getResultSetType());
//setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
public static class BoundSqlSqlSource implements SqlSource {
private BoundSql boundSql;
public BoundSqlSqlSource(BoundSql boundSql) {
this.boundSql = boundSql;
}
public BoundSql getBoundSql(Object parameterObject) {
return boundSql;
}
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
//suffix = properties.get("dirname").toString();
}
}
以MySql数据库分页举例,做一个MySqlPaginationPlugin
@Intercepts({@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MySqlPaginationPlugin extends PaginationBasePlugin {
@Override
protected String paginationSql(String sql,Object args) {
if(args instanceof Map){
if(((Map) args).containsKey("pagination")){
Map map = (Map) args;
RowBounds rowBounds = (RowBounds) map.get("pagination");
sql = sql+" limit " + rowBounds.getOffset()+ ","+rowBounds.getLimit(); //分页了
}
}
return sql;
}
}
MySql的分页比较简单,其他数据库的分页要求对sql参数进行分离和复杂点的修改,这些玩意大家自己就会倒腾了,网上有很多代码,再次不弄了
用法如下,从代码中可以看出,只要Xml Mapper的Sql语句输入参数为map类型,并且里面含有pagination键值就可以了,否则不分页
class ClientGateway {
static forceAsListOps = ["selectClient"];
def queryClient(RowBounds rowBounds) {
HashMap map = new HashMap()
map.put("pagination", rowBounds); //关键标志
sqlMapper.selectList("selectClient", map);
}
}
pagination的值为一个RowBounds类型,这个是MyBatis里面带的东西,我就直接拿来用了,反正就那两个属性offset,limit
这样同一个sql语句既可以支持分页也可以不支持分页,避免了写两套相同的sql,不好维护
<mapper namespace="client">
<select id="selectClient" parameterType="map" resultType="client">
select * from client
</select>
</mapper>
那么其中这个sql语句的count又如何不写两套sql弄出来呢?
同样道理,自己在map里面再加个特殊的标记,就可以一个sql语句也支持count了
综上,通过MyBatis的插件拦截sql是一个sql语句既可以直接执行,也可以支持分页和获取所有行数。提高了可维护性。
代码中的pagination字符串自己弄成常量吧,不满意的地方可以自己修改,思路就是这样了,我使着挺好用。
分享到:
相关推荐
用于 Grails 框架的 MyBatis 插件 基于原始 Grails-iBatis 插件:Brian Sanders ( ) Grails 插件主页: : 修改: 命名约定的一些变化 添加了对多个数据源的完全支持 Grails 2.0 插件重构 最小 Grails 依赖项 ...
eclipse插件、用来开发grails(路漫漫其修远兮、吾将上下而求索)
供初学者使用,在grails中只有list(自动生成)中有分页实现,而自己新增的页面中需自己实现分页,该文档中描述了如何实现分页以及注意点
elasticsearch-grails-plugin, 恢复的ElasticSearch grails插件 Elasticsearch插件插件这个项目是一个基于Elasticsearch的插件,这个项目是基于的人完成的伟大工作的。你为什么想要为原来的Elasticsearch插件提供...
概括Grails插件将Primefaces集成到Grails项目中。 带有Java JDK 1.7的最低Grails版本是2.3.7,并且依赖项具有以下版本: 核心JSF 2.2 Primefaces 5.2 Apache MyFaces 2.2.8 可以在上找到源代码安装通过在BuildConfig...
这是一个 grails 插件,它在您的 Grails 应用程序中集成了一个 url 缩短器。 安装 在BuildConfig添加以下依赖项: compile " :url-shortener:<version> " 配置 安装插件后,您必须将以下配置添加到Config.groovy...
restful-api, Grails插件,方便暴露非平凡的RESTful api #RESTful API插件文档尽管随后的更改可能不是向后兼容的,但 ##Status的生产质量也是如此。##Overview在附带的"介绍了rest式API插件插件。"演示文稿中提供了...
本文内容包括:ShortenUrl插件简介创建TinyUrl类测试TinyUrl类创建IsGd类创建ShortenUrl服务打包并部署插件结束语下载参考资料在这个“精通Grails”系列中,ScottDavis将向您展示如何创建您自己的Grails插件。...
MongoDB Grails插件 MongoDB Grails插件主要作为称为“ mongo”的Spring bean公开给Grails应用程序。 然后,只需添加“ mongo”,Grails类就可以轻松地在整个代码中使用它。 支持依赖注入(域/控制器/服务)的类的...
grails的插件系统也是其亮点之一。首先,和rails,django等web框架类似,基于微内核的思想,插件(可重用模块)是框架的一等公民。grails除了核心模块以外的功能几乎都是通过插件方式实现的。实际上,一个grails插件...
Grails插件实验 定义Grails 3.0插件域类是可扩展的 SO的详细信息: 该项目包含一个名为security的插件和一个名为bookstore的应用程序以测试该插件。...还是应该设计插件以允许应用程序扩展域类的其他方式?
Grails Pjax插件Pjax在Grails中。 Pjax类似于(turbolinks)[ ,在'A'标签,按钮和表单上工作。 参见_pjaxHeader grails templtate文件中的演示代码。 ## Pjax是什么? Pjax是一个jQuery插件,它使用ajax和pushState...
QRCreator Grails 插件 Grails 插件,用于在基于代码的网页中嵌入二维码 它允许您在 QR 码的中心放置一个徽标,并完全控制纠错级别和相当的区域大小。 可以从服务器上的本地文件或从 URL 加载徽标。 使用提供的 ...
在help菜单选择Install New Software…
eclipse插件grails(groovy)配置方法
ElasticSearch Grails 插件有一个新的维护者! 请浏览 Noam Y. Tenne fork 以获取插件源代码的新更新: 此版本的主要新功能之一是能够通过插件使用任何 gorm-datastore, 所以你不再绑定到Hibernate插件。 虽然 ...
这是一个Grails插件,可以在Grails Web项目中使用Akka actor(本地和远程)。 分配 grails-akka-.zip用于插件源分发-这是推荐版本,因为此插件的二进制版本不包含必需的jar 依存关系 一个Servlet 3.x容器来运行Web...
Grails构建在开源技术如Spring、Hibernate和SiteMesh之上,提供了一个类似于Rails的平台可以与Java平台无缝集成的。但Grails比Rails具有更强的可像Java那样成熟的虚拟机,并且能够给企业级的服务提供成熟的支持。...
原型Grails插件该插件将 , 和 Javascript库集成到Grails中。 在1.4之前的Grails版本中,这些库默认包含在Grails中。 从Grails 1.4开始, 是Grails发行版中的默认Javascript库,此插件为那些愿意使用Prototype或希望...