zoukankan      html  css  js  c++  java
  • web-分页显示

    在了解到通过数组分页的缺陷后,我们发现不能每次都对数据库中的所有数据都检索。然后在程序中对获取到的大量数据进行二次操作,这样对空间和性能都是极大的损耗。所以我们希望能直接在数据库语言中只检索符合条件的记录,不需要在通过程序对其作处理。这时,Sql语句分页技术横空出世。

    实现:通过sql语句实现分页也是非常简单的,只是需要改变我们查询的语句就能实现了,即在sql语句后面添加limit分页语句。

    首先还是在StudentMapper接口中添加sql语句查询的方法,如下:

    1 List<Student> queryStudentsBySql(Map<String,Object> data);

    然后在StudentMapper.xml文件中编写sql语句通过limiy关键字进行分页:

    1 <select id="queryStudentsBySql" parameterType="map" resultMap="studentmapper">
    2     select * from student limit #{currIndex} , #{pageSize}
    3 </select>

    接下来还是在IStuService接口中定义方法,并且在StuServiceIml中对sql分页实现。

    sql分页语句如下:

    1 select * from table limit index, pageSize;

    所以在service中计算出currIndex:要开始查询的第一条记录的索引。

    结果:

    从输出结果可以看出和数组分页的结果是一致的,因此sql语句的分页也是没问题的。

    缺点:虽然这里实现了按需查找,每次检索得到的是指定的数据。但是每次在分页的时候都需要去编写limit语句,很冗余。而且不方便统一管理,维护性较差。所以我们希望能够有一种更方便的分页实现。

    拦截器分页

      上面提到的数组分页和sql语句分页都不是我们今天讲解的重点,今天需要实现的是利用拦截器达到分页的效果。自定义拦截器实现了拦截所有以ByPage结尾的查询语句,并且利用获取到的分页相关参数统一在sql语句后面加上limit分页的相关语句,一劳永逸。不再需要在每个语句中单独去配置分页相关的参数了。

      首先我们看一下拦截器的具体实现,在这里我们需要拦截所有以ByPage结尾的所有查询语句,因此要使用该拦截器实现分页功能,那么再定义名称的时候需要满足它拦截的规则(以ByPage结尾),如下所示:

     1 package com.cbg.interceptor;
     2 import org.apache.ibatis.executor.Executor;
     3 import org.apache.ibatis.executor.parameter.ParameterHandler;
     4 import org.apache.ibatis.executor.resultset.ResultSetHandler;
     5 import org.apache.ibatis.executor.statement.StatementHandler;
     6 import org.apache.ibatis.mapping.MappedStatement;
     7 import org.apache.ibatis.plugin.*;
     8 import org.apache.ibatis.reflection.MetaObject;
     9 import org.apache.ibatis.reflection.SystemMetaObject;
    10 import java.sql.Connection;
    11 import java.util.Map;
    12 import java.util.Properties;
    13 
    14 /**
    15 * @Intercepts 说明是一个拦截器
    16 * @Signature 拦截器的签名
    17 * type 拦截的类型 四大对象之一( Executor,ResultSetHandler,ParameterHandler,StatementHandler)
    18 * method 拦截的方法
    19 * args 参数
    20 */
    21 @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
    22 public class MyPageInterceptor implements Interceptor {
    23 
    24 //每页显示的条目数
    25 private int pageSize;
    26 //当前现实的页数
    27 private int currPage;
    28 
    29 private String dbType;
    30 
    31 @Override
    32 public Object intercept(Invocation invocation) throws Throwable {
    33     //获取StatementHandler,默认是RoutingStatementHandler
    34     StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    35     //获取statementHandler包装类
    36     MetaObject MetaObjectHandler = SystemMetaObject.forObject(statementHandler);
    37     //分离代理对象链
    38     while (MetaObjectHandler.hasGetter("h")) {
    39         Object obj = MetaObjectHandler.getValue("h");
    40         MetaObjectHandler = SystemMetaObject.forObject(obj);
    41     }
    42     while (MetaObjectHandler.hasGetter("target")) {
    43         Object obj = MetaObjectHandler.getValue("target");
    44         MetaObjectHandler = SystemMetaObject.forObject(obj);
    45     }
    46     //获取连接对象
    47     //Connection connection = (Connection) invocation.getArgs()[0];
    48     //object.getValue("delegate"); 获取StatementHandler的实现类
    49     //获取查询接口映射的相关信息
    50     MappedStatement mappedStatement = (MappedStatement) MetaObjectHandler.getValue("delegate.mappedStatement");
    51     String mapId = mappedStatement.getId();
    52     //statementHandler.getBoundSql().getParameterObject();
    53     //拦截以.ByPage结尾的请求,分页功能的统一实现
    54     if (mapId.matches(".+ByPage$")) {
    55         //获取进行数据库操作时管理参数的handler
    56         ParameterHandler parameterHandler = (ParameterHandler) MetaObjectHandler.getValue("delegate.parameterHandler");
    57         //获取请求时的参数
    58         Map<String, Object> paraObject = (Map<String, Object>) parameterHandler.getParameterObject();
    59         //也可以这样获取
    60         //paraObject = (Map<String, Object>) statementHandler.getBoundSql().getParameterObject();
    61         //参数名称和在service中设置到map中的名称一致
    62         currPage = (int) paraObject.get("currPage");
    63         pageSize = (int) paraObject.get("pageSize");
    64         String sql = (String) MetaObjectHandler.getValue("delegate.boundSql.sql");
    65         //也可以通过statementHandler直接获取
    66         //sql = statementHandler.getBoundSql().getSql();
    67         //构建分页功能的sql语句
    68         String limitSql;
    69         sql = sql.trim();
    70         limitSql = sql + " limit " + (currPage - 1) * pageSize + "," + pageSize;
    71         //将构建完成的分页sql语句赋值个体'delegate.boundSql.sql',偷天换日
    72         MetaObjectHandler.setValue("delegate.boundSql.sql", limitSql);
    73     }
    74     //调用原对象的方法,进入责任链的下一级
    75     return invocation.proceed();
    76 }
    77 
    78 //获取代理对象
    79 @Override
    80     public Object plugin(Object o) {
    81     //生成object对象的动态代理对象
    82     return Plugin.wrap(o, this);
    83 }
    84 
    85 //设置代理对象的参数
    86 @Override
    87     public void setProperties(Properties properties) {
    88         //如果项目中分页的pageSize是统一的,也可以在这里统一配置和获取,这样就不用每次请求都传递pageSize参数了。参数是在配置拦截器时配置的。
    89         String limit1 = properties.getProperty("limit", "10");
    90         this.pageSize = Integer.valueOf(limit1);
    91         this.dbType = properties.getProperty("dbType", "mysql");
    92     }
    93 }

    上面即是拦截器功能的实现,在intercept方法中获取到select标签和sql语句的相关信息,拦截所有以ByPage结尾的select查询,并且统一在查询语句后面添加limit分页的相关语句,统一实现分页功能。

  • 相关阅读:
    XML Schema的基本语法(转)
    Lambda 表达式参考
    LINQ查询表达式示例
    Jackson ObjectMapper类使用解析
    hdu 1242 c++ 广搜
    poj 1111 新手路过
    poj 1664 放苹果
    poj 3126 简单广搜题
    poj 1256 全排列
    HDU 2544 最短路
  • 原文地址:https://www.cnblogs.com/lkwkk/p/14215252.html
Copyright © 2011-2022 走看看