目前关于mybaties分页:html
1、自定义实现,代码量比较少,简单,比较灵活。如下为具体的集成步骤:java
一、在User.xml中加入select节点,并组装分页SQLmysql
<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>
二、在IUserOperation.java中加入Mapping对应的方法
public List<Article> getUserArticlesByLimit(int id,int start,int limit);
三、修改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条数据git
二。经过自定义插件的形式,实现分页也是最好的,也叫作分页拦截器 实现步骤以下:github
插件支持MySQL和Oracle两种数据库,经过方法名关键字ListPage去匹配,有才进行分页处理,而且不用在Mapping中写分页代码。web
一、在User.xml中添加查询语句spring
<!-- 插件式分页查询测试 --> <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>
二、在IUserOperation.java中添加接口
public List<Article> selectArticleListPage(@Param("page")PageInfo page,@Param("userid") int userid);
三、如下是插件实现的三个类
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:sql
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(); } } } }
四、在Configuration.xml中配置插件apache
<?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才能被拦截。不然将不会分页处理
五、在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; }
六、页面文件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>
三。
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; } }
第一步: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 //一、设置分页信息,包括当前页数和每页显示的总计数 16 PageHelper.startPage(page, rows); 17 //二、执行查询 18 TbItemExample example = new TbItemExample(); 19 List<TbItem> list = tbItemMapper.selectByExample(example); 20 //三、获取分页查询后的数据 21 PageInfo<TbItem> pageInfo = new PageInfo<>(list); 22 //四、封装须要返回的分页实体 23 DatagridResult result = new DatagridResult(); 24 //设置获取到的总记录数total: 25 result.setTotal(pageInfo.getTotal()); 26 //设置数据集合rows: 27 result.setRows(list); 28 29 return result; 30 }
第一步: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
三、控制器层的使用 复制代码 @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"; }
四、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