在web項目中,分頁應用最普遍,簡單記錄一下我在實際項目中使用的分頁思路;
1、RowBounds分頁,這種分頁不推薦使用,RowBounds在處理分頁時,只是簡單的把offset之前的數據都skip掉,超過limit之后的數據不取出,簡單點說,就是先把數據全部查詢到ResultSet,然后從ResultSet中取出offset和limit之間的數據,這 就實現了分頁查詢。Mysql中可以使用limit語句,但limit並不是標准SQL中的,如果是其它的數據庫,則需要使用其它語句。
2、一般項目中使用mybatis逆向工程生成類和映射文件,所以可以使用Page工具類和自動生成 的..Example相結合,來完成頁面的分頁顯示,多條件查詢,多條件排序等。
3、還可以使用paperhelper分頁插件進行分頁查詢,功能很強大。
4、排序在分頁的中的應用。
//使用example.setOrderByClause("字段名1 ASC/DESC,字段名2 ASC/DESC,...");
/** * 分頁查詢 */ @Override public PageInfo<Userinfo> findAllByPage(int currentPage, int pageSize) { UserinfoExample example = new UserinfoExample(); String orderByClause = "uid asc,uname desc"; example.setOrderByClause(orderByClause); PageHelper.startPage(currentPage, pageSize,orderByClause); List<Userinfo> list = userinfoMapper.selectByExample(example); PageInfo<Userinfo> pageInfo = new PageInfo<>(list); return pageInfo; }
//在paperhelper插件中可以使用PageHelper.startPage(currentPage, pageSize,orderByClause);
/** * 分頁查詢 */ @Override public PageInfo<Userinfo> findAllByPage(int currentPage, int pageSize) { String orderByClause = "uid asc,uname desc"; PageHelper.startPage(currentPage, pageSize,orderByClause); List<Userinfo> list = userinfoMapper.selectByExample(null); PageInfo<Userinfo> pageInfo = new PageInfo<>(list); return pageInfo; }
5、使用Page工具類和逆向工程中的example實現分頁。
1)先創建Page類
public class Page { private int currentPageNo; // 當前頁碼 private int pageSize; // 頁面大小,即每頁顯示記錄數 private int count; // 記錄總數 private int sumPage; // 總頁數 List<Userinfo> userlist; // 每頁新聞集合
//計算總頁數 public int getSumPage() { return sumPage=count%pageSize==0?count/pageSize:count/pageSize+1; } //省去其他set/get方法 }
2)給Example類添加參數,生成set/get方法
public class UserinfoExample { /** * 分頁 */ private Integer currentPage; private Integer pageSize; public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public Integer getCurrentPage() { return currentPage; } public void setCurrentPage(Integer currentPage) { this.currentPage = currentPage; } }
3)修改mapper.xml中的selectByExample方法
//在if條件最后添加分頁的判斷 <if test="currentPage != null and pageSize !=null and pageSize !=0"> limit #{currentPage},#{pageSize} </if>
4)service層的查詢方法
/** * page 類 和example結合使用
* 傳入當前頁、頁大小和對象,可以實現按條件查詢
* 最后返回page對象到前台
*/ @Override public Page findAllByPageAndExample(int currentPage, int pageSize,Userinfo userinfo) { Page page = new Page(); page.setCount(userinfoMapper.count()); if(currentPage ==0 ) { currentPage = 1; } if(pageSize ==0) { pageSize = 10; } page.setCurrentPageNo(currentPage); page.setPageSize(pageSize); //處理當前頁數大於總頁數的問題 if(currentPage > page.getSumPage()){ currentPage = page.getSumPage(); page.setCurrentPageNo(currentPage); } //處理當前頁數小於第一頁的問題 if(currentPage < 0){ currentPage = 1; page.setCurrentPageNo(currentPage); } //按條件查詢 UserinfoExample example = new UserinfoExample(); Criteria ce = example.createCriteria(); if(userinfo.getUname() != null && userinfo.getUname().trim().length()>0) { ce.andUnameLike("%"+userinfo.getUname()+"%"); } example.setCurrentPage((page.getCurrentPageNo()-1)*pageSize); example.setPageSize(page.getPageSize()); page.setUserlist(userinfoMapper.selectByExample(example)); return page; }
5)controller層的代碼
/** * page 類 和example結合使用
* 我這里需要實現按條件查詢和設置每頁顯示的頁大小,所以頁大小的值和按條件查詢的對象信息都保存在session中
* 前台每次需要修改查詢條件時,先異步請求到后台,將值set到session中,再發起請求獲取數據。
*/ @RequestMapping("findAll") public String findAllByPageAndExample(Integer c,HttpServletRequest request,HttpSession session) { Userinfo userinfo = (Userinfo)session.getAttribute("userinfo"); if(userinfo == null) { userinfo = new Userinfo(); } int pageSize = (int) session.getAttribute("pageSize"); Page page = userinfoServiceImpl.findAllByPageAndExample(c, pageSize,userinfo); request.setAttribute("page", page); request.setAttribute("userinfo", (Userinfo)session.getAttribute("userinfo")); return "index"; }
6、paperhelper插件的使用(我創建的是maven項目)
1)引入jar包
<!-- 引入分頁插件,paperhelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.6</version> </dependency>
2)配置mybatis.xml文件(也可以選擇在spring配置文件中配置,此處在mybatis.xml文件中配置)
<!-- 配置分頁插件 --> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 設置數據庫類型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六種數據庫--> <property name="helperDialect" value="mysql"/> <!-- reasonable:分頁合理化參數,默認值為false。當該參數設置為 true 時,pageNum<=0 時會查詢第一頁, pageNum>pages(超過總數時),會查詢最后一頁。默認false 時,直接根據參數進行查詢。 --> <property name="reasonable" value="true"/> </plugin> </plugins>
3)service層的描述
同樣可以傳入對象,使用example實現按條件查詢,paperhelper插件實現的很全,直接將PageInfo發給前台,PageInfo中就包含了分頁查詢的所有信息,在PageInfo中都可以拿到。
/** * 分頁查詢 */ @Override public PageInfo<Userinfo> findAllByPage(int currentPage, int pageSize) { UserinfoExample example = new UserinfoExample(); String orderByClause = "uid asc,uname desc"; example.setOrderByClause(orderByClause); PageHelper.startPage(currentPage, pageSize); List<Userinfo> list = userinfoMapper.selectByExample(example); PageInfo<Userinfo> pageInfo = new PageInfo<>(list); return pageInfo; }
4)controller層
@RequestMapping("findAll") public String findAll(int currentPage,int pageSize ,HttpSession session,HttpServletRequest request) { PageInfo<Userinfo> pageInfo = userinfoServiceImpl.findAllByPage(currentPage, pageSize); request.setAttribute("pageInfo", pageInfo); return "index"; }
7、PageInfo類的屬性
public class PageInfo<T> implements Serializable { private static final long serialVersionUID = 1L; //當前頁 private int pageNum; //每頁的數量 private int pageSize; //當前頁的數量 private int size; //當前頁面第一個元素在數據庫中的行號 private int startRow; //當前頁面最后一個元素在數據庫中的行號 private int endRow; //總記錄數 private long total; //總頁數 private int pages; //結果集 private List<T> list; //前一頁 private int prePage; //下一頁 private int nextPage; //是否為第一頁 private boolean isFirstPage = false; //是否為最后一頁 private boolean isLastPage = false; //是否有前一頁 private boolean hasPreviousPage = false; //是否有下一頁 private boolean hasNextPage = false; //導航頁碼數 private int navigatePages; //所有導航頁號 private int[] navigatepageNums; //導航條上的第一頁 private int navigateFirstPage; //導航條上的最后一頁 private int navigateLastPage; public PageInfo() { } //省去其他方法 }