Mybatis包分页查询java公共类

  分页----对于数据量非常大的查询中。是不可缺少的。

mybatis底层的分页sql语句因为须要我们自己去手动写。而实现分页显示的时候我们须要依据分页查询条件查询符合条件的总记录数和记录的具体情况。因此,若是不去实现封装一下的话,我们须要写两条SQL语句去实现它。一次用于查询记录数目。一次用于查询分页显示的具体记录。

当项目中碰到非常多须要分页的时候,我们便对于每个Mapper.xml文件都须要去写两条SQL语句。

极其麻烦。代码重用----必须重用。所以,一个公共方法的分页需求应运而生。

直接上分页公共代码,事实上现的原理是使用了拦截器的拦截作用。拦截一类分页查询的请求。我们依据传进来的參数是否是须要interceptor()方法中拦截的參数,是的话则拦截,并运行对应的SQL追加,否则,不进行追加。直接放行。视作普通查询。

 

   须要在Mybatis的配置文件里配置载入server的时候载入该公共类:mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8"?>

       <!DOCTYPE configuration

       PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

      "http://mybatis.org/dtd/mybatis-3-config.dtd">

       <configuration>

                <properties></properties>

               <plugins>

                       <plugin interceptor="com.iboxpay.clear.filter.PaginationInterceptor"></plugin>

              </plugins>

      </configuration>





import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.Properties;    



import org.apache.ibatis.executor.parameter.ParameterHandler;

import org.apache.ibatis.executor.statement.StatementHandler;    

import org.apache.ibatis.mapping.BoundSql;    

import org.apache.ibatis.mapping.MappedStatement;

import org.apache.ibatis.plugin.Interceptor;    

import org.apache.ibatis.plugin.Intercepts;    

import org.apache.ibatis.plugin.Invocation;    

import org.apache.ibatis.plugin.Plugin;    

import org.apache.ibatis.plugin.Signature;    

import org.apache.ibatis.reflection.MetaObject;    

import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

import org.apache.ibatis.reflection.factory.ObjectFactory;

import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;

import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;

import org.apache.ibatis.session.RowBounds;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;



/**

 * 分页拦截器

 * @since 10.20.2014

 */

@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})})    

public class PaginationInterceptor implements Interceptor {

    

    private final Logger logger = LoggerFactory.getLogger(PaginationInterceptor.class);



    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();

    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();

        

    public Object intercept(Invocation invocation) throws Throwable {  

        

         StatementHandler statementHandler = (StatementHandler) invocation.getTarget();  

         MetaObject metaStatementHandler = MetaObject.forObject(statementHandler,  

         DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);  

         

         // 分离代理对象链(因为目标类可能被多个拦截器拦截,从而形成多次代理。通过以下的两次循环  

         // 能够分离出最原始的的目标类)  

         while (metaStatementHandler.hasGetter("h")) {  

             Object object = metaStatementHandler.getValue("h");  

             metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY,   

             DEFAULT_OBJECT_WRAPPER_FACTORY);  

         }

         // 分离最后一个代理对象的目标类  

         while (metaStatementHandler.hasGetter("target")) {  

             Object object = metaStatementHandler.getValue("target");  

             metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY,   

             DEFAULT_OBJECT_WRAPPER_FACTORY);  

         }

         

         MappedStatement mappedStatement = (MappedStatement)   

         metaStatementHandler.getValue("delegate.mappedStatement");  

         // 仅仅重写须要分页的sql语句。通过MappedStatement的ID匹配。默认重写以Page结尾的  

         //  MappedStatement的sql  

         BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");  

         Object parameterObject = boundSql.getParameterObject();  

         

         if(parameterObject instanceof  PageParam){

             if (parameterObject == null) {

                 throw new NullPointerException("parameterObject is null!");  

             } else {

                 PageParam page = (PageParam)parameterObject;  

                 String sql = boundSql.getSql();  

                 // 重写sql  

                 String pageSql = buildPageSql(sql, page);  

                 metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);  

                 metaStatementHandler.setValue("delegate.rowBounds.offset",   

                 RowBounds.NO_ROW_OFFSET);  

                 metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);  

                 Connection connection = (Connection) invocation.getArgs()[0];  

                 // 重设分页參数里的总页数等  

                 setPageParameter(sql, connection, mappedStatement, boundSql, page);  

             }

         }  

         // 将运行权交给下一个拦截器  

         return invocation.proceed();  

     }  

    

    private String buildPageSql(String sql, PageParam page) {  

        if (page != null) {  

            StringBuilder pageSql = new StringBuilder();  

                pageSql = buildPageSqlForOracle(sql, page);  

            return pageSql.toString();  

        } else {

            return sql;  

        }  

    }  

    

    public StringBuilder buildPageSqlForOracle(String sql, PageParam page) {

        StringBuilder pageSql = new StringBuilder(100);

        String beginrow = String.valueOf((page.getCurrentPage() - 1) * page.getPageSize());  

        String endrow = String.valueOf(page.getCurrentPage() * page.getPageSize());  

        pageSql.append("select * from ( select temp.*, rownum row_id from ( ");  

        pageSql.append(sql);  

        pageSql.append(" ) temp where rownum <= ").append(endrow);

        pageSql.append(") where row_id > ").append(beginrow);

        return pageSql;  

    }  

    

    /**

     * 从数据库里查询总的记录数并计算总页数,回写进分页參数<code>PageParam</code>,这样调用  

     * 者就可用通过 分页參数<code>PageParam</code>获得相关信息。

*  

     * @param sql

     * @param connection

     * @param mappedStatement

     * @param boundSql

     * @param page

     * @throws SQLException

     */  

    private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement,  

            BoundSql boundSql, PageParam page) throws SQLException {  

        // 记录总记录数  

        String countSql = "select count(0) from (" + sql + ")";  

        PreparedStatement countStmt = null;  

        ResultSet rs = null;  

        try {  

            countStmt = connection.prepareStatement(countSql);  

            BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,  

                    boundSql.getParameterMappings(), boundSql.getParameterObject());  

            setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());  

            rs = countStmt.executeQuery();

            int totalCount = 0;  

            if (rs.next()) {

                totalCount = rs.getInt(1);  

            }

            page.setTotalCount(totalCount);  

            int totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 0) ? 0 : 1);  

            page.setTotalPage(totalPage);

        } catch (SQLException e) {  

            logger.error("exception", e);

        } finally {

            try {  

                rs.close();  

            } catch (SQLException e) {  

                logger.error("exception", e);  

            }  

            try {  

                countStmt.close();  

            } catch (SQLException e) {  

                logger.error("exception", e);  

            }  

        }  

    }  

      

    private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql,  

            Object parameterObject) throws SQLException {  

        ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);  

        parameterHandler.setParameters(ps);  

    }  

    

    @Override

    public Object plugin(Object target) {    

        if (target instanceof StatementHandler) {  

            return Plugin.wrap(target, this);

        } else {

            return target;

        }

    }

    

    @Override

    public void setProperties(Properties arg0) {    

    }

}

将日志的过滤模式调到DEBUG模式,控制台能够打印出SQL

使用上述方法处理的分页查询,其仅仅须要一条SQL语句就能够(Mapper.xml文件的SQL)

<select id="selectChannelSettleByParam" parameterType="PageParam" resultMap="RS_CHANNELSETTLE">

        <![CDATA[

            select  *

        ]]>

            from channlsettle where 1=1

            <if test="params.channelSettleModel.channelId != null and 1000 != params.channelSettleModel.channelId">AND CHANNL_ID=#{params.channelSettleModel.channelId}</if>

            <if test="params.channelSettleModel.clearStartTime != null and '' != params.channelSettleModel.clearStartTime">

                <![CDATA[  

                       AND to_number(CLEAR_DATE) >= to_number(substr(#{params.channelSettleModel.clearStartTime},0,8))   

                 ]]>

            </if>

            <if test="params.channelSettleModel.clearEndTime != null and '' != params.channelSettleModel.clearEndTime">

                <![CDATA[  

                       AND to_number(CLEAR_DATE) <= to_number(substr(#{params.channelSettleModel.clearEndTime},0,8))   

                 ]]>

            </if>

            order by INSTDATE desc

    </select>



控制台打印的SQL:

第一条:select count(0) from (select *  from channlsettle where 1=1 AND CHANNL_ID=? AND to_number(CLEAR_DATE) >= to_number(substr(?

,0,8)) AND to_number(CLEAR_DATE) <= to_number(substr(?

,0,8)) order by INSTDATE desc)




第二条:select * from ( select temp.*, rownum row_id from ( select *  from channlsettle where 1=1 AND CHANNL_ID=? AND to_number(CLEAR_DATE) >= to_number(substr(?

,0,8)) AND to_number(CLEAR_DATE) <= to_number(substr(?

,0,8)) order
by INSTDATE desc ) temp where rownum <= 20) where row_id > 0



从而让公共类实现了我们须要在Mapper.xml配置文件里反复写入两条SQL的工作,以后没一个分页查询都能够使用。


版权声明:本文博客原创文章,博客,未经同意,不得转载。

Mybatis包分页查询java公共类的更多相关文章

  1. springmvc+mybatis 实现分页查询

    为简化分页功能,设计了一个分页的JSP标签,只需要在页面使用分页标签,就可以完成所有页面的分页功能. 1. 项目结构和数据库设计 (1) 项目结构: (2) 数据库设计 2. PageModel.ja ...

  2. SpringBoot整合Mybatis关于分页查询的方法

    最近公司在用到SpringBoot整合Mybatis时当web端页面数据增多时需要使用分页查询以方便来展示数据.本人对分页查询进行了一些步骤的总结,希望能够帮助到有需要的博友.如有更好的方式,也希望评 ...

  3. spring-boot 集合mybatis 的分页查询

    spring-boot 集合mybatis 的github分页查询 一.依赖包 <!-- mysql 数据库驱动. --> <dependency> <groupId&g ...

  4. mybatis之分页查询

    1)StudentDao.java /** * 持久层*/ public class StudentDao { /** * 增加学生 */ public void add(Student studen ...

  5. 亿级别记录的mongodb分页查询java代码实现

    1.准备环境 1.1 mongodb下载 1.2 mongodb启动 C:\mongodb\bin\mongod --dbpath D:\mongodb\data 1.3 可视化mongo工具Robo ...

  6. 使用mybatis实现分页查询示例代码分析

    *******************************************分页查询开始*************************************************** ...

  7. Mybatis 使用分页查询亿级数据 性能问题 DB使用ORACLE

    一般用到了mybatis框架分页就不用自己写了 直接用RowBounds对象就可以实现,但这个性能确实很低 今天我用到10w级得数据分页查询,到后面几页就迭代了很慢 用于记录 1.10万级数据如下 [ ...

  8. mybatis中分页查询

    1 如果在查询方法中有多个参数,可以使用map对象将所有数据都存储进去.比如分页查询,需要用到两个参数,可以将这两个参数包装到map中. 例子:分页查询 dao层方法 public List<S ...

  9. Mybatis的分页查询

    示例1:查询业务员的联系记录 1.控制器代码(RelationController.java) //分页列出联系记录 @RequestMapping(value="toPage/custom ...

随机推荐

  1. 使用Canvas和Paint自己绘制折线图

    主要用于Canvas一个特别简单的小demo. 能够手动点击看每一个月份的数据.很easy.就是用paint在canvas上画出来的. 主要内容就是计算左边价格的位置,以下日期的位置,三根虚线的位置, ...

  2. 【Spark亚太研究院系列】Spark道路的真正的主人-第一章 构建Spark星团(第五步)(6)

    结束historyserver例如,下面的命令可以看到: 第四步:验证Hadoop分布式集群 首先在hdfs文件系统上创建两个文件夹.创建步骤例如以下所看到的: watermark/2/text/aH ...

  3. BZOJ 3122 SDOI2013 随机数发生器 数论 EXBSGS

    标题效果:给定一列数X(i+1)=(a*Xi+b)%p 最低要求i>0.所以Xi=t 0.0 这个问题可以1A那很棒 首先讨论特殊情况 如果X1=t ans=1 如果a=0 ans=b==t? ...

  4. window.open的小技巧分享(转)

    今天再次谈起window.open是因为发现了一个比较好玩的小技巧,详细内容我们稍后详细说明.       聊到window.open,不得不说明一下他的使用方法,主要有两种形式:   window. ...

  5. FTP定时批量下载文件(SHELL脚本及使用方法 ) (转)--good

    #/bin/bash URL="http://192.168.5.100/xxx.php" check() { RESULT=$(curl -s $URL) echo $RESUL ...

  6. Android新浪微博client(七)——ListView图片异步加载、高速缓存

    原文出自:方杰|p=193" style="color:rgb(202,0,0); text-decoration:none; font-size:14px; font-famil ...

  7. Lucene于Directory

    MMapDirectory从继承FSDirectory,抵抗jre至今未能解决Mmap close不回收空间(直到full gc恢复之前,)的bug,lucene使用hack资料恢复(只要sun ja ...

  8. Hadoop Java Hdfs API

    1. 在本地文件系统生成一个文本文件,,读入文件,将其第101-120字节的内容写入HDFS成为一个新文件2. 在HDFS中生成文本文件,读入这个文件,将其第101-120字节的内容写入本地文件系统成 ...

  9. 如何关闭CBox(2.4版本号)强制升级的形式

    从今天开始2.4.0.9版本号CBox,提示检测到新的版本号,能够使用后必须更新为新版本号,提示表见下面的例子. 此次升级是强制升级.假如你选择不升级(单击窗体上的升级提示右下角"辍学but ...

  10. DDD Reference

    版权声明:本文博客原创文章.博客,未经同意,不得转载.