`
qixin000
  • 浏览: 21295 次
  • 性别: Icon_minigender_1
  • 来自: 黑龙江
文章分类
社区版块
存档分类
最新评论

Grails插件MyBatis分页设计

阅读更多
新的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字符串自己弄成常量吧,不满意的地方可以自己修改,思路就是这样了,我使着挺好用。
0
1
分享到:
评论
2 楼 qixin000 2013-12-18  
天涯海角tour 写道
如果加入缓存的话还可以分页面吗,能查询到第二页面吗?

没有改动内部的缓存机制,缓存应该好用!第二页能查到,你试试吧,呵呵!
1 楼 天涯海角tour 2013-12-11  
如果加入缓存的话还可以分页面吗,能查询到第二页面吗?

相关推荐

    Grails-MyBatis:用于 Grails 框架的 MyBatis 插件

    用于 Grails 框架的 MyBatis 插件 基于原始 Grails-iBatis 插件:Brian Sanders ( ) Grails 插件主页: : 修改: 命名约定的一些变化 添加了对多个数据源的完全支持 Grails 2.0 插件重构 最小 Grails 依赖项 ...

    eclipse开发grails插件

    Grails的核心特性包括MVC架构、领域驱动设计(GORM)、自动化构建过程以及丰富的插件系统。通过Eclipse的插件,我们可以更好地在Java环境中集成Grails开发,享受无缝切换的便利。 接下来,我们将讨论**Eclipse插件...

    grails实现分页技术

    在Grails这个基于Groovy的敏捷开发框架中,实现分页功能对于任何Web应用程序都是至关重要的,特别是当...此外,你还可以考虑使用现有的分页插件,如`grails-paginate-taglib`,它们提供了更丰富的功能和更简洁的API。

    elasticsearch-grails-plugin, 恢复的ElasticSearch grails插件.zip

    elasticsearch-grails-plugin, 恢复的ElasticSearch grails插件 Elasticsearch插件插件这个项目是一个基于Elasticsearch的插件,这个项目是基于的人完成的伟大工作的。你为什么想要为原来的Elasticsearch插件提供...

    Grails安装SVN客户端插件指导手册

    为了在Grails环境中方便地使用SVN,我们需要安装一个支持SVN的客户端插件,这就是Subclipse。本指南将详细介绍如何在Grails环境中安装Subclipse插件。 首先,启动你的Eclipse集成开发环境(IDE),这是Grails通常...

    eclipse插件grails(groovy)

    Eclipse 插件 Grails(Groovy)是一个强大的开发工具,它使得在Eclipse环境中进行Groovy和Grails应用的开发变得更为便捷。Groovy是一种动态、面向对象的编程语言,而Grails则是一个基于Groovy的开源Web应用框架,...

    primefaces:Grails插件将Primefaces集成到Grails项目中

    概括Grails插件将Primefaces集成到Grails项目中。 带有Java JDK 1.7的最低Grails版本是2.3.7,并且依赖项具有以下版本: 核心JSF 2.2 Primefaces 5.2 Apache MyFaces 2.2.8 可以在上找到源代码安装通过在BuildConfig...

    grails-url-shortener:这是一个 grails 插件,它在你的 Grails 应用程序中集成了一个自定义的 url 缩短器

    这是一个 grails 插件,它在您的 Grails 应用程序中集成了一个 url 缩短器。 安装 在BuildConfig添加以下依赖项: compile " :url-shortener:&lt;version&gt; " 配置 安装插件后,您必须将以下配置添加到Config.groovy...

    grails 中文文档+grails-fckeditor-0.9.5.zip插件

    2. MVC架构:Grails遵循Model-View-Controller(MVC)设计模式,通过GORM(Grails Object Relational Mapping)进行数据访问,使用GSP(Groovy Server Pages)作为视图模板,Controller负责业务逻辑处理。...

    restful-api, Grails插件,方便暴露非平凡的RESTful api.zip

    restful-api, Grails插件,方便暴露非平凡的RESTful api #RESTful API插件文档尽管随后的更改可能不是向后兼容的,但 ##Status的生产质量也是如此。##Overview在附带的"介绍了rest式API插件插件。"演示文稿中提供了...

    mongodb-grails:集成了MongoDB的Grails插件

    MongoDB Grails插件 MongoDB Grails插件主要作为称为“ mongo”的Spring bean公开给Grails应用程序。 然后,只需添加“ mongo”,Grails类就可以轻松地在整个代码中使用它。 支持依赖注入(域/控制器/服务)的类的...

    grails框架

    grails的插件系统也是其亮点之一。首先,和rails,django等web框架类似,基于微内核的思想,插件(可重用模块)是框架的一等公民。grails除了核心模块以外的功能几乎都是通过插件方式实现的。实际上,一个grails插件...

    grails-plugin-experiment:测试Grails插件开发的地方

    Grails插件实验 定义Grails 3.0插件域类是可扩展的 SO的详细信息: 该项目包含一个名为security的插件和一个名为bookstore的应用程序以测试该插件。...还是应该设计插件以允许应用程序扩展域类的其他方式?

    Grails Wed开发课程设计

    【Grails Web开发课程设计】是一门以Grails框架为核心的Web应用开发实践课程。Grails是一种基于Groovy语言的开源框架,它旨在提高开发效率,同时保持与Java平台的紧密集成,利用Spring、Hibernate和SiteMesh等成熟的...

    grails-pjax:Grails Pjax插件云可帮助您在Grails中使用pjax

    Grails Pjax插件Pjax在Grails中。 Pjax类似于(turbolinks)[ ,在'A'标签,按钮和表单上工作。 参见_pjaxHeader grails templtate文件中的演示代码。 ## Pjax是什么? Pjax是一个jQuery插件,它使用ajax和pushState...

    qrcreator:Grails插件二维码生成器

    QRCreator Grails 插件 Grails 插件,用于在基于代码的网页中嵌入二维码 它允许您在 QR 码的中心放置一个徽标,并完全控制纠错级别和相当的区域大小。 可以从服务器上的本地文件或从 URL 加载徽标。 使用提供的 ...

    Grails plugin: Calendar

    1. **集成易用**:Grails插件设计的目标之一就是易于集成到现有项目中。"Calendar"插件应该提供简单的方法,使得开发者可以快速地在他们的应用程序中添加一个交互式的日历组件。 2. **模板和样式**:插件可能包含了...

    grails-4.0.4.zip

    7. **MVC架构**:Grails遵循经典的Model-View-Controller设计模式,有助于组织代码并分离关注点。模型负责业务逻辑,视图负责展示,控制器则协调两者之间的交互。 8. **热部署**:Grails支持热部署,即在开发过程中...

    Grails Grails Grails

    3. **插件系统**:Grails 插件是一组可重用的功能模块,可以快速增强应用程序的功能,如Spring Security、Asset Pipeline等。 4. **命令行工具**:Grails 提供强大的命令行工具,支持创建项目、运行应用、生成代码...

Global site tag (gtag.js) - Google Analytics