目前關於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