zoukankan      html  css  js  c++  java
  • MyBatis3-实现MyBatis分页

    目前关于mybaties分页:

    一、自定义实现,代码量比较少,简单,比较灵活。以下为具体的集成步骤:

    1、在User.xml中加入select节点,并组装分页SQL

    <select id="getUserArticlesByLimit" parameterType="int" resultMap="resultUserArticleList">
            select user.id,user.userName,user.userAddress,article.id as aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{arg0} limit #{arg1},#{arg2}
        </select>

    2、在IUserOperation.java中加入Mapping对应的方法
    public List<Article> getUserArticlesByLimit(int id,int start,int limit);

    3、修改UserController.java中获取数据的方法,改成分页方法,并传入指定参数

    package com.jsoft.testmybatis.controller;
    
    import java.util.List;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.jsoft.testmybatis.inter.IUserOperation;
    import com.jsoft.testmybatis.models.Article;
    
    @Controller
    @RequestMapping("/article")
    public class UserController {
        @Autowired
        IUserOperation userMapper;
    
        @RequestMapping("/list")
        public ModelAndView listall(HttpServletRequest request,HttpServletResponse response){
            List<Article> articles=userMapper.getUserArticlesByLimit(1,0,2); 
            ModelAndView mav=new ModelAndView("/article/list");
            mav.addObject("articles",articles);
            return mav;
        }
    }
    

      意思是获取用户1的数据,从第0行开始的2条数据

    二。通过自定义插件的形式,实现分页也是最好的,也叫做分页拦截器  实现步骤如下:

    插件支持MySQL和Oracle两种数据库,通过方法名关键字ListPage去匹配,有才进行分页处理,并且不用在Mapping中写分页代码。

    1、在User.xml中添加查询语句

     <!-- 插件式分页查询测试 -->
        <select id="selectArticleListPage" resultMap="resultUserArticleList">
            select user.id,user.userName,user.userAddress,article.id as aid,article.title,article.content from user,article where user.id=article.userid and user.id=#{userid}
        </select>

    2、在IUserOperation.java中添加接口
    public List<Article> selectArticleListPage(@Param("page")PageInfo page,@Param("userid") int userid);
    3、以下是插件实现的三个类
    PageInfo.java
    package com.jsoft.testmybatis.util;
    
    import java.io.Serializable;
    
    public class PageInfo implements Serializable {
    
        private static final long serialVersionUID = 587754556498974978L;
    
        // pagesize ,每一页显示多少
        private int showCount = 3;
        // 总页数
        private int totalPage;
        // 总记录数
        private int totalResult;
        // 当前页数
        private int currentPage;
        // 当前显示到的ID, 在mysql limit 中就是第一个参数.
        private int currentResult;
        private String sortField;
        private String order;
    
        public int getShowCount() {
            return showCount;
        }
    
        public void setShowCount(int showCount) {
            this.showCount = showCount;
        }
    
        public int getTotalPage() {
            return totalPage;
        }
    
        public void setTotalPage(int totalPage) {
            this.totalPage = totalPage;
        }
    
        public int getTotalResult() {
            return totalResult;
        }
    
        public void setTotalResult(int totalResult) {
            this.totalResult = totalResult;
        }
    
        public int getCurrentPage() {
            return currentPage;
        }
    
        public void setCurrentPage(int currentPage) {
            this.currentPage = currentPage;
        }
    
        public int getCurrentResult() {
            return currentResult;
        }
    
        public void setCurrentResult(int currentResult) {
            this.currentResult = currentResult;
        }
    
        public String getSortField() {
            return sortField;
        }
    
        public void setSortField(String sortField) {
            this.sortField = sortField;
        }
    
        public String getOrder() {
            return order;
        }
    
        public void setOrder(String order) {
            this.order = order;
        }
    
    }
    

      

    ReflectHelper.java:

    package com.jsoft.testmybatis.util;
    
    import java.lang.reflect.Field;
    
    public class ReflectHelper {
        public static Field getFieldByFieldName(Object obj, String fieldName) {
            for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
                try {
                    return superClass.getDeclaredField(fieldName);
                } catch (NoSuchFieldException e) {
                }
            }
            return null;
        }
    
        /**
         * Obj fieldName的获取属性值.
         * 
         * @param obj
         * @param fieldName
         * @return
         * @throws SecurityException
         * @throws NoSuchFieldException
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
            Field field = getFieldByFieldName(obj, fieldName);
            Object value = null;
            if (field != null) {
                if (field.isAccessible()) {
                    value = field.get(obj);
                } else {
                    field.setAccessible(true);
                    value = field.get(obj);
                    field.setAccessible(false);
                }
            }
            return value;
        }
    
        /**
         * obj fieldName设置的属性值.
         * 
         * @param obj
         * @param fieldName
         * @param value
         * @throws SecurityException
         * @throws NoSuchFieldException
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         */
        public static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            if (field.isAccessible()) {
                field.set(obj, value);
            } else {
                field.setAccessible(true);
                field.set(obj, value);
                field.setAccessible(false);
            }
        }
    
    }
    

      

    PagePlugin.java:

    package com.jsoft.testmybatis.util;
    
    import java.lang.reflect.Field;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.List;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.xml.bind.PropertyException;
    
    import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
    import org.apache.ibatis.executor.ErrorContext;
    import org.apache.ibatis.executor.ExecutorException;
    import org.apache.ibatis.executor.statement.BaseStatementHandler;
    import org.apache.ibatis.executor.statement.RoutingStatementHandler;
    import org.apache.ibatis.executor.statement.StatementHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.mapping.MappedStatement;
    import org.apache.ibatis.mapping.ParameterMapping;
    import org.apache.ibatis.mapping.ParameterMode;
    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.property.PropertyTokenizer;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.type.TypeHandler;
    import org.apache.ibatis.type.TypeHandlerRegistry;
    
    @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
    public class PagePlugin implements Interceptor {
    
        private static String dialect = "";
        private static String pageSqlId = "";
    
        @SuppressWarnings("unchecked")
        public Object intercept(Invocation ivk) throws Throwable {
    
            if (ivk.getTarget() instanceof RoutingStatementHandler) {
                RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget();
                BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate");
                MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement");
    
                if (mappedStatement.getId().matches(pageSqlId)) {
                    BoundSql boundSql = delegate.getBoundSql();
                    Object parameterObject = boundSql.getParameterObject();
                    if (parameterObject == null) {
                        throw new NullPointerException("parameterObject error");
                    } else {
                        Connection connection = (Connection) ivk.getArgs()[0];
                        String sql = boundSql.getSql();
                        String countSql = "select count(0) from (" + sql + ") myCount";
                        System.out.println("总数sql 语句:" + countSql);
                        PreparedStatement countStmt = connection.prepareStatement(countSql);
                        BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
                        setParameters(countStmt, mappedStatement, countBS, parameterObject);
                        ResultSet rs = countStmt.executeQuery();
                        int count = 0;
                        if (rs.next()) {
                            count = rs.getInt(1);
                        }
                        rs.close();
                        countStmt.close();
    
                        PageInfo page = null;
                        if (parameterObject instanceof PageInfo) {
                            page = (PageInfo) parameterObject;
                            page.setTotalResult(count);
                        } else if (parameterObject instanceof Map) {
                            Map<String, Object> map = (Map<String, Object>) parameterObject;
                            page = (PageInfo) map.get("page");
                            if (page == null)
                                page = new PageInfo();
                            page.setTotalResult(count);
                        } else {
                            Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "page");
                            if (pageField != null) {
                                page = (PageInfo) ReflectHelper.getValueByFieldName(parameterObject, "page");
                                if (page == null)
                                    page = new PageInfo();
                                page.setTotalResult(count);
                                ReflectHelper.setValueByFieldName(parameterObject, "page", page);
                            } else {
                                throw new NoSuchFieldException(parameterObject.getClass().getName());
                            }
                        }
                        String pageSql = generatePageSql(sql, page);
                        System.out.println("page sql:" + pageSql);
                        ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
                    }
                }
            }
            return ivk.proceed();
        }
    
        private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
            ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
            List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
            if (parameterMappings != null) {
                Configuration configuration = mappedStatement.getConfiguration();
                TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
                MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
                for (int i = 0; i < parameterMappings.size(); i++) {
                    ParameterMapping parameterMapping = parameterMappings.get(i);
                    if (parameterMapping.getMode() != ParameterMode.OUT) {
                        Object value;
                        String propertyName = parameterMapping.getProperty();
                        PropertyTokenizer prop = new PropertyTokenizer(propertyName);
                        if (parameterObject == null) {
                            value = null;
                        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                            value = parameterObject;
                        } else if (boundSql.hasAdditionalParameter(propertyName)) {
                            value = boundSql.getAdditionalParameter(propertyName);
                        } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) {
                            value = boundSql.getAdditionalParameter(prop.getName());
                            if (value != null) {
                                value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
                            }
                        } else {
                            value = metaObject == null ? null : metaObject.getValue(propertyName);
                        }
                        TypeHandler typeHandler = parameterMapping.getTypeHandler();
                        if (typeHandler == null) {
                            throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
                        }
                        typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
                    }
                }
            }
        }
    
        private String generatePageSql(String sql, PageInfo page) {
            if (page != null && (dialect != null || !dialect.equals(""))) {
                StringBuffer pageSql = new StringBuffer();
                if ("mysql".equals(dialect)) {
                    pageSql.append(sql);
                    pageSql.append(" limit " + page.getCurrentResult() + "," + page.getShowCount());
                } else if ("oracle".equals(dialect)) {
                    pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
                    pageSql.append(sql);
                    pageSql.append(")  tmp_tb where ROWNUM<=");
                    pageSql.append(page.getCurrentResult() + page.getShowCount());
                    pageSql.append(") where row_id>");
                    pageSql.append(page.getCurrentResult());
                }
                return pageSql.toString();
            } else {
                return sql;
            }
        }
    
        public Object plugin(Object arg0) {
            // TODO Auto-generated method stub
            return Plugin.wrap(arg0, this);
        }
    
        public void setProperties(Properties p) {
            dialect = p.getProperty("dialect");
            if (dialect == null || dialect.equals("")) {
                try {
                    throw new PropertyException("dialect property is not found!");
                } catch (PropertyException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            pageSqlId = p.getProperty("pageSqlId");
            if (dialect == null || dialect.equals("")) {
                try {
                    throw new PropertyException("pageSqlId property is not found!");
                } catch (PropertyException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    
    }
    

      

    4、在Configuration.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>
        <typeAliases>
            <typeAlias alias="PageInfo" type="com.jsoft.testmybatis.util.PageInfo" />
        </typeAliases>
        <plugins>
            <plugin interceptor="com.jsoft.testmybatis.util.PagePlugin">
                <property name="dialect" value="mysql" />
                <property name="pageSqlId" value=".*ListPage.*" />
            </plugin>
        </plugins>
    
    </configuration>
    

      

    注意:这个插件定义了一个规则,也就是在mapper中SQL语句的id必须包含ListPage才能被拦截。否则将不会分页处理

    5、在UserController.java中添加测试的Controller

    @RequestMapping("/pagelist")
        public ModelAndView pageList(HttpServletRequest request, HttpServletResponse response) {
            int currentPage = request.getParameter("page") == null ? 1 : Integer.parseInt(request.getParameter("page"));
            int pageSize = 3;
            if (currentPage <= 0) {
                currentPage = 1;
            }
            int currentResult = (currentPage - 1) * pageSize;
    
            System.out.println(request.getRequestURI());
            System.out.println(request.getQueryString());
    
            PageInfo page = new PageInfo();
            page.setShowCount(pageSize);
            page.setCurrentResult(currentResult);
            List<Article> articles = userMapper.selectArticleListPage(page, 1);
    
            System.out.println(page);
    
            int totalCount = page.getTotalResult();
    
            int lastPage = 0;
            if (totalCount % pageSize == 0) {
                lastPage = totalCount % pageSize;
            } else {
                lastPage = 1 + totalCount / pageSize;
            }
    
            if (currentPage >= lastPage) {
                currentPage = lastPage;
            }
    
            String pageStr = "";
    
            pageStr = String.format("<a href="%s">上一页</a>    <a href="%s">下一页</a>", request.getRequestURI() + "?page=" + (currentPage - 1), request.getRequestURI() + "?page=" + (currentPage + 1));
    
            // 制定视图,也就是list.jsp
            ModelAndView mav = new ModelAndView("/article/pagelist");
            mav.addObject("articles", articles);
            mav.addObject("pageStr", pageStr);
            return mav;
        }
    

      6、页面文件pagelist.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <c:forEach items="${articles}" var="item">  
            ${item.id }--${item.title }--${item.content }<br />
        </c:forEach>
        <div style="padding:20px;">${pageStr}</div>
    </body>
    </html>
    

      

    三。

    Mybatis分页插件PageHelper简单使用

    Config PageHelper
    
    1. Using in mybatis-config.xml
    
    <!-- 
        In the configuration file, 
        plugins location must meet the requirements as the following order:
        properties?, settings?, 
        typeAliases?, typeHandlers?, 
        objectFactory?,objectWrapperFactory?, 
        plugins?, 
        environments?, databaseIdProvider?, mappers?
    -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- config params as the following -->
            <property name="param1" value="value1"/>
        </plugin>
    </plugins>
    2. Using in Spring application.xml
    
    config org.mybatis.spring.SqlSessionFactoryBean as following:
    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <!-- other configuration -->
      <property name="plugins">
        <array>
          <bean class="com.github.pagehelper.PageInterceptor">
            <property name="properties">
              <!-- config params as the following -->
              <value>
                param1=value1
              </value>
            </property>
          </bean>
        </array>
      </property>
    </bean>

    我使用第一中方法:
    
    复制代码
    <!-- 配置分页插件 -->
        <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor">
                <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
                <property name="helperDialect" value="mysql"/>
            </plugin>
        </plugins>
    

      

    2,编写mapper.xml文件
    测试工程就不复杂了,简单的查询一个表,没有条件
    
    <select id="selectByPageAndSelections" resultMap="BaseResultMap">
            SELECT *
            FROM doc
            ORDER BY doc_abstract
        </select>
    

      

    然后在Mapper.java中编写对应的接口

    public List<Doc> selectByPageAndSelections();
    3,分页
    @Service
    public class DocServiceImpl implements IDocService {
        @Autowired
        private DocMapper docMapper;
    
        @Override
        public PageInfo<Doc> selectDocByPage1(int currentPage, int pageSize) {
            PageHelper.startPage(currentPage, pageSize);
            List<Doc> docs = docMapper.selectByPageAndSelections();
            PageInfo<Doc> pageInfo = new PageInfo<>(docs);
            return pageInfo;
        }
    }
    

      

    Spring集成PageHelper:

    第一步:pom文件引入依赖

    1 <!-- mybatis的分页插件 -->
    2 <dependency>
    3     <groupId>com.github.pagehelper</groupId>
    4     <artifactId>pagehelper</artifactId>
    5 </dependency>

    第二步:MyBatis的核心配置文件中引入配置项

    <?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>
          <!-- 【mybatis的核心配置文件】 -->
     
          <!-- 批量设置别名(可以不配) 作用:就是在mapper.xml文件中直接写类名,也可以不用写全路径名。 -->
         <typeAliases>
             <package name="cn.e3mall.manager.po" />
         </typeAliases>
     
         <!-- 配置mybatis的分页插件PageHelper -->
         <plugins>
             <!-- com.github.pagehelper为PageHelper类所在包名 -->
             <plugin interceptor="com.github.pagehelper.PageHelper">
                 <!-- 设置数据库类型Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库 -->
                 <property name="dialect" value="mysql"/>
             </plugin>
         </plugins>
     
     </configuration>
    

      

    第三步:业务逻辑实现分页功能,我们只需将当前查询的页数page和每页显示的总条数rows传进去,然后Pagehelper已经帮我们分好数据了,只需在web层获取数据即可。
    
     1 //分页查询商品列表:
     2     @Override
     3     public DatagridResult itemList(Integer page, Integer rows) {
     4         //为了程序的严谨性,判断非空:
     5         if(page == null){
     6             page = 1;   //设置默认当前页
     7         }
     8         if(page <= 0){
     9             page = 1;
    10         }
    11         if(rows == null){
    12             rows = 30;    //设置默认每页显示的商品数(因为jsp页面上默认写的就是30条)
    13         }
    14         
    15         //1、设置分页信息,包括当前页数和每页显示的总计数
    16         PageHelper.startPage(page, rows);
    17         //2、执行查询
    18         TbItemExample example = new TbItemExample();
    19         List<TbItem> list = tbItemMapper.selectByExample(example);
    20         //3、获取分页查询后的数据
    21         PageInfo<TbItem> pageInfo = new PageInfo<>(list);
    22         //4、封装需要返回的分页实体
    23         DatagridResult result = new DatagridResult();
    24         //设置获取到的总记录数total:
    25         result.setTotal(pageInfo.getTotal());
    26         //设置数据集合rows:
    27         result.setRows(list);
    28         
    29         return result;
    30     }
    

      

    SpringBoot集成PageHelper:

    第一步:pom文件还是需要引入依赖
    
    1 <dependency>
    2      <groupId>com.github.pagehelper</groupId>
    3      <artifactId>pagehelper</artifactId>
    4      <version>4.1.6</version>
    5 </dependency>
    

    第二步:这次直接是在项目的入口类application.java中直接设置PageHelper插件即可

    //配置mybatis的分页插件pageHelper
          @Bean
          public PageHelper pageHelper(){
              PageHelper pageHelper = new PageHelper();
             Properties properties = new Properties();
            properties.setProperty("offsetAsPageNum","true");
              properties.setProperty("rowBoundsWithCount","true");
             properties.setProperty("reasonable","true");
              properties.setProperty("dialect","mysql");    //配置mysql数据库的方言
             pageHelper.setProperties(properties);
            return pageHelper;
        }
    

      

    第三步:同理,使用插件实现分页功能,方式还是一样,只需将当前查询的页数和每页显示的条数穿进去即可,直接�源码

    这是需要用到的分页实体,各位可以直接享用。

    package com.zxz.utils;
     2 
     3 /**
     4  * 分页bean
     5  */
     6 
     7 import java.util.List;
     8 
     9 public class PageBean<T> {
    10     // 当前页
    11     private Integer currentPage = 1;
    12     // 每页显示的总条数
    13     private Integer pageSize = 10;
    14     // 总条数
    15     private Integer totalNum;
    16     // 是否有下一页
    17     private Integer isMore;
    18     // 总页数
    19     private Integer totalPage;
    20     // 开始索引
    21     private Integer startIndex;
    22     // 分页结果
    23     private List<T> items;
    24 
    25     public PageBean() {
    26         super();
    27     }
    28 
    29     public PageBean(Integer currentPage, Integer pageSize, Integer totalNum) {
    30         super();
    31         this.currentPage = currentPage;
    32         this.pageSize = pageSize;
    33         this.totalNum = totalNum;
    34         this.totalPage = (this.totalNum+this.pageSize-1)/this.pageSize;
    35         this.startIndex = (this.currentPage-1)*this.pageSize;
    36         this.isMore = this.currentPage >= this.totalPage?0:1;
    37     }
    38 
    39     public Integer getCurrentPage() {
    40         return currentPage;
    41     }
    42 
    43     public void setCurrentPage(Integer currentPage) {
    44         this.currentPage = currentPage;
    45     }
    46 
    47     public Integer getPageSize() {
    48         return pageSize;
    49     }
    50 
    51     public void setPageSize(Integer pageSize) {
    52         this.pageSize = pageSize;
    53     }
    54 
    55     public Integer getTotalNum() {
    56         return totalNum;
    57     }
    58 
    59     public void setTotalNum(Integer totalNum) {
    60         this.totalNum = totalNum;
    61     }
    62 
    63     public Integer getIsMore() {
    64         return isMore;
    65     }
    66 
    67     public void setIsMore(Integer isMore) {
    68         this.isMore = isMore;
    69     }
    70 
    71     public Integer getTotalPage() {
    72         return totalPage;
    73     }
    74 
    75     public void setTotalPage(Integer totalPage) {
    76         this.totalPage = totalPage;
    77     }
    78 
    79     public Integer getStartIndex() {
    80         return startIndex;
    81     }
    82 
    83     public void setStartIndex(Integer startIndex) {
    84         this.startIndex = startIndex;
    85     }
    86 
    87     public List<T> getItems() {
    88         return items;
    89     }
    90 
    91     public void setItems(List<T> items) {
    92         this.items = items;
    93     }
    94 }
    

      分页功能源码(web层和service层)。

    @Override
          public List<Item> findItemByPage(int currentPage,int pageSize) {
              //设置分页信息,分别是当前页数和每页显示的总记录数【记住:必须在mapper接口中的方法执行之前设置该分页信息】
              PageHelper.startPage(currentPage, pageSize);
             
              List<Item> allItems = itemMapper.findAll();        //全部商品
              int countNums = itemMapper.countItem();            //总记录数
             PageBean<Item> pageData = new PageBean<>(currentPage, pageSize, countNums);
              pageData.setItems(allItems);
             return pageData.getItems();
         }



    /**
           * 商品分页功能(集成mybatis的分页插件pageHelper实现)
           * 
           * @param currentPage    :当前页数
           * @param pageSize        :每页显示的总记录数
           * @return
           */
          @RequestMapping("/itemsPage")
          @ResponseBody
         public List<Item> itemsPage(int currentPage,int pageSize){
             return itemService.findItemByPage(currentPage, pageSize);
         }
     

      到这儿呢,MyBatis的分页插件PageHelper就完全和SpringBoot集成到一起了

    另外一种实现模式:

    直接在配置application.yml文件添加

    #配置分页插件pagehelper
    pagehelper:
        helperDialect: mysql
        reasonable: true
        supportMethodsArguments: true
        params: count=countSql
    

      

    3、控制器层的使用
    
    复制代码
    @Autowired
        PostInfoService postInfo;
        
        @RequestMapping("/info")
        public String getAll(@RequestParam(value="pn",defaultValue="1") Integer pn,Model model){
            //获取第1页,5条内容,默认查询总数count
            /* 第一个参数是第几页;第二个参数是每页显示条数 */
            PageHelper.startPage(pn, 3);
            List<PostInfor> postIn = postInfo.getAll();
            System.out.println(postIn+"===========");
            //用PageInfo对结果进行包装
            
            PageInfo<PostInfor> page = new PageInfo<PostInfor>(postIn);
            model.addAttribute("pageInfo", page);
            return "index";
        }
    

      

    4、index页面-分页部分
    
    复制代码
    <!-- 分页 -->
    <div class="ui circular labels" style="float: right;">
        <a class="ui label">当前第 ${pageInfo.pageNum }页,总${pageInfo.pages }
    页,总 ${pageInfo.total } 条记录</a>
        <a class="ui label" href="info?pn=1">首页</a>
        <c:if test="${pageInfo.hasPreviousPage }">
            <a class="ui label" href="info?pn=${pageInfo.pageNum-1 }">«</a>
        </c:if>
    
        <c:forEach items="${pageInfo.navigatepageNums }" var="page_Num">
            <c:if test="${page_Num == pageInfo.pageNum }">
                <a class="ui label" href="info?pn=${page_Num}">${page_Num}</a>
            </c:if>
            <c:if test="${page_Num != pageInfo.pageNum }">
                <a class="ui label" href="info?pn=${page_Num}">${page_Num }</a>
            </c:if>
        </c:forEach>
        
        <c:if test="${pageInfo.hasNextPage }">
            <a class="ui label" href="info?pn=${pageInfo.pageNum+1 }">»</a>
        </c:if>
        <a class="ui label" href="info?pn=${pageInfo.pages}">末页</a>
    </div>
    <!-- 分页 end-->
    

      

    3. 如何在代码中使用
    阅读前请注意看重要提示
    
    分页插件支持以下几种调用方式:
    
    //第一种,RowBounds方式的调用
    List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));
    
    //第二种,Mapper接口方式的调用,推荐这种使用方式。
    PageHelper.startPage(1, 10);
    List<Country> list = countryMapper.selectIf(1);
    
    //第三种,Mapper接口方式的调用,推荐这种使用方式。
    PageHelper.offsetPage(1, 10);
    List<Country> list = countryMapper.selectIf(1);
    
    //第四种,参数方法调用
    //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
    public interface CountryMapper {
        List<Country> selectByPageNumSize(
                @Param("user") User user,
                @Param("pageNum") int pageNum, 
                @Param("pageSize") int pageSize);
    }
    //配置supportMethodsArguments=true
    //在代码中直接调用:
    List<Country> list = countryMapper.selectByPageNumSize(user, 1, 10);
    
    //第五种,参数对象
    //如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
    //有如下 User 对象
    public class User {
        //其他fields
        //下面两个参数名和 params 配置的名字一致
        private Integer pageNum;
        private Integer pageSize;
    }
    //存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
    public interface CountryMapper {
        List<Country> selectByPageNumSize(User user);
    }
    //当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
    List<Country> list = countryMapper.selectByPageNumSize(user);
    
    //第六种,ISelect 接口方式
    //jdk6,7用法,创建接口
    Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
        @Override
        public void doSelect() {
            countryMapper.selectGroupBy();
        }
    });
    //jdk8 lambda用法
    Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(()-> countryMapper.selectGroupBy());
    
    //也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
    pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
        @Override
        public void doSelect() {
            countryMapper.selectGroupBy();
        }
    });
    //对应的lambda用法
    pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> countryMapper.selectGroupBy());
    
    //count查询,返回一个查询语句的count数
    long total = PageHelper.count(new ISelect() {
        @Override
        public void doSelect() {
            countryMapper.selectLike(country);
        }
    });
    //lambda
    total = PageHelper.count(()->countryMapper.selectLike(country));
    下面对最常用的方式进行详细介绍
    
    1). RowBounds方式的调用
    List<Country> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(1, 10));
    使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。
    
    分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页。
    
    关于这种方式的调用,有两个特殊的参数是针对 RowBounds 的,你可以参看上面的 场景一 和 场景二
    
    注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:
    
    //这种情况下也会进行物理分页查询
    List<Country> selectAll(RowBounds rowBounds);  
    注意: 由于默认情况下的 RowBounds 无法获取查询总数,分页插件提供了一个继承自 RowBounds 的 PageRowBounds,这个对象中增加了 total 属性,执行分页查询后,可以从该属性得到查询总数。
    
    2). PageHelper.startPage 静态方法调用
    除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。
    
    在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。
    
    例一:
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);
    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>
    assertEquals(182, ((Page) list).getTotal());
    例二:
    //request: url?pageNum=1&pageSize=10
    //支持 ServletRequest,Map,POJO 对象,需要配合 params 参数
    PageHelper.startPage(request);
    //紧跟着的第一个select方法会被分页
    List<Country> list = countryMapper.selectIf(1);
    
    //后面的不会被分页,除非再次调用PageHelper.startPage
    List<Country> list2 = countryMapper.selectIf(null);
    //list1
    assertEquals(2, list.get(0).getId());
    assertEquals(10, list.size());
    //分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
    //或者使用PageInfo类(下面的例子有介绍)
    assertEquals(182, ((Page) list).getTotal());
    //list2
    assertEquals(1, list2.get(0).getId());
    assertEquals(182, list2.size());
    例三,使用PageInfo的用法:
    //获取第1页,10条内容,默认查询总数count
    PageHelper.startPage(1, 10);
    List<Country> list = countryMapper.selectAll();
    //用PageInfo对结果进行包装
    PageInfo page = new PageInfo(list);
    //测试PageInfo全部属性
    //PageInfo包含了非常全面的分页属性
    assertEquals(1, page.getPageNum());
    assertEquals(10, page.getPageSize());
    assertEquals(1, page.getStartRow());
    assertEquals(10, page.getEndRow());
    assertEquals(183, page.getTotal());
    assertEquals(19, page.getPages());
    assertEquals(1, page.getFirstPage());
    assertEquals(8, page.getLastPage());
    assertEquals(true, page.isFirstPage());
    assertEquals(false, page.isLastPage());
    assertEquals(false, page.isHasPreviousPage());
    assertEquals(true, page.isHasNextPage());
    3). 使用参数方式
    想要使用参数方式,需要配置 supportMethodsArguments 参数为 true,同时要配置 params 参数。 例如下面的配置:
    
    <plugins>
        <!-- com.github.pagehelper为PageHelper类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
            <property name="supportMethodsArguments" value="true"/>
            <property name="params" value="pageNum=pageNumKey;pageSize=pageSizeKey;"/>
    	</plugin>
    </plugins>
    在 MyBatis 方法中:
    
    List<Country> selectByPageNumSize(
            @Param("user") User user,
            @Param("pageNumKey") int pageNum, 
            @Param("pageSizeKey") int pageSize);
    当调用这个方法时,由于同时发现了 pageNumKey 和 pageSizeKey 参数,这个方法就会被分页。params 提供的几个参数都可以这样使用。
    
    除了上面这种方式外,如果 User 对象中包含这两个参数值,也可以有下面的方法:
    
    List<Country> selectByPageNumSize(User user);
    当从 User 中同时发现了 pageNumKey 和 pageSizeKey 参数,这个方法就会被分页。
    
    注意:pageNum 和 pageSize 两个属性同时存在才会触发分页操作,在这个前提下,其他的分页参数才会生效。
    
    3). PageHelper 安全调用
    1. 使用 RowBounds 和 PageRowBounds 参数方式是极其安全的
    2. 使用参数方式是极其安全的
    3. 使用 ISelect 接口调用是极其安全的
    ISelect 接口方式除了可以保证安全外,还特别实现了将查询转换为单纯的 count 查询方式,这个方法可以将任意的查询方法,变成一个 select count(*) 的查询方法。
    
    4. 什么时候会导致不安全的分页?
    PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。
    
    只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。
    
    如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。
    
    但是如果你写出下面这样的代码,就是不安全的用法:
    
    PageHelper.startPage(1, 10);
    List<Country> list;
    if(param1 != null){
        list = countryMapper.selectIf(param1);
    } else {
        list = new ArrayList<Country>();
    }
    这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。
    
    上面这个代码,应该写成下面这个样子:
    
    List<Country> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        list = countryMapper.selectIf(param1);
    } else {
        list = new ArrayList<Country>();
    }
    这种写法就能保证安全。
    
    如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:
    
    List<Country> list;
    if(param1 != null){
        PageHelper.startPage(1, 10);
        try{
            list = countryMapper.selectAll();
        } finally {
            PageHelper.clearPage();
        }
    } else {
        list = new ArrayList<Country>();
    }
    这么写很不好看,而且没有必要。
    
    4. MyBatis 和 Spring 集成示例
    如果和Spring集成不熟悉,可以参考下面两个
    
    只有基础的配置信息,没有任何现成的功能,作为新手入门搭建框架的基础
    
    集成 Spring 3.x
    集成 Spring 4.x
    这两个集成框架集成了 PageHelper 和 通用 Mapper。
    
    5. Spring Boot 集成示例
    https://github.com/abel533/MyBatis-Spring-Boot
    

      

  • 相关阅读:
    webkit之滚动条美化
    意想不到的javascript
    html5 的存储
    javascript 中的number
    javascript 模板
    关于ajax的跨域
    一个菜鸟眼中的前端
    【转】python
    [转]修改python默认的编码方式
    搞科研
  • 原文地址:https://www.cnblogs.com/huojg-21442/p/10030484.html
Copyright © 2011-2022 走看看