<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
專案中資料分頁是一個很常見的需求,目前大部分專案都會使用pagehelper進行分頁,那麼在使用的過程中是否考慮如下問題?
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pagehelper.version}</version> </dependency>
pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql
分頁引數類 public class PageParam<T> implements Serializable { private static final long serialVersionUID = -7916211163897873899L; private int pageNum=1; private int pageSize=10; //條件引數 private T param; //排序欄位 private String orderBy; public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public T getParam() { return param; } public void setParam(T param) { this.param = param; } public String getOrderBy() { return orderBy; } public void setOrderBy(String orderBy) { //需要注意sql注入 this.orderBy = orderBy; } } 分頁結果類 public class PagedList<T> implements Serializable { private static final long serialVersionUID = -1253790062865437768L; private int pageNum = 1; private List<T> data = null; private int pageCount = 0; private int recordCount = -1; private int pagingType = 0; private int pageSize; private String orderBy; /** * @return the pageSize */ public int getPageSize() { return pageSize; } /** * @param pageSize * the pageSize to set */ public void setPageSize(int pageSize) { if (pageSize <= 0) { return; } this.pageSize = pageSize; } /** * @return the pageCount */ public int getPageCount() { return pageCount; } /** * @param pageCount * the pageCount to set */ public void setPageCount(int pageCount) { if (pageCount <= 0) { return; } this.pageCount = pageCount; } /** * @return the recordCount */ public int getRecordCount() { return recordCount; } /** * @param recordCount * the recordCount to set */ public void setRecordCount(int recordCount) { this.recordCount = recordCount; calcPageCount(); } private void calcPageCount() { if (this.recordCount < 0) { return; } int tmp = this.recordCount % getPageSize(); this.pageCount = (tmp == 0 ? (this.recordCount / getPageSize()) : (this.recordCount / getPageSize() + 1)); if (this.pageNum > this.pageCount && this.pageCount != 0) { this.pageNum = this.pageCount; } this.pageNum = this.pageCount; } public void setData(List<T> data) { this.data = data; if (ObjectUtil.isNotEmpty(data) && this.recordCount == -1) { this.recordCount = data.size(); } } public List<T> getData() { return data; } /** * @return the pagingType */ public int getPagingType() { return pagingType; } /** * @param pagingType * the pagingType to set */ public void setPagingType(int pagingType) { this.pagingType = pagingType; } public void setOrderBy(String orderBy) { this.orderBy = orderBy; } public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public String getOrderBy() { return orderBy; } } 分頁工具類 public class PageUtils implements Serializable { private static final long serialVersionUID = 377943433889798799L; public static <T> PagedList<T> exportPagedList(PageParam<T> pageParam) { PagedList<T> pl = new PagedList<T>(); // pagesize int pageSize = pageParam.getPageSize(); if (pageSize <= 0) { pageSize = 10; } else { pl.setPageSize(pageSize); } int pageNum = pageParam.getPageNum(); pl.setPageNum(pageNum); String orderBy= pageParam.getOrderBy(); if(StringUtil.isNotEmpty(orderBy)) { //防止sql注入 String orderBySql=SQLFilter.sqlInject(orderBy); pl.setOrderBy(orderBySql); } return pl; } public static <T>PagedList<T> toPageList(PageInfo<T> spage) { PagedList<T> pagedList = new PagedList<T>(); pagedList.setPageSize((int) spage.getPageSize()); pagedList.setPageNum((int) spage.getPageNum()); pagedList.setRecordCount((int) spage.getTotal()); pagedList.setData(spage.getList()); pagedList.setPageCount((int) spage.getPages()); return pagedList; } }
@PostMapping("getPageList") public Result getPageList(@RequestBody PageParam<TUser> pageParm) { //接收引數 PagedList<TUser> pl =PageUtils.exportPagedList(pageParm); return Result.success(userService.queryPageList(pl, pageParm.getParam())); } public PagedList<TUser> queryPageList(PagedList<TUser> page,TUser user) { PageInfo<TUser> pageInfo= PageHelper.startPage(page).doSelectPageInfo(()-> list(user)); //轉換結果 return PageUtils.toPageList(pageInfo); }
{ "pageSize":10, "pageNum":"1", //查詢條件 "param":{ "name":"張三210001" }, //排序欄位 "orderBy":"age desc" }
2022-04-15 22:26:39.914 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - ==> Preparing: SELECT * FROM t_user u LEFT JOIN t_user_role ur ON ur.userOid = u.oid WHERE name = ? order by age desc LIMIT ?
2022-04-15 22:26:39.919 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - ==> Parameters: 張三210001(String), 10(Integer)
2022-04-15 22:26:40.267 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - <== Total: 1
基礎的分頁查詢已經發完成了,下面解答上面的問題的方法
對於前段傳入的排序欄位,我們需要進行SQL過濾處理,關於這個問題其實在上述的分頁封裝類中已經進行了解決
範例程式碼:
public class SQLFilter { public static String sqlInject(String str) { if (StringUtil.isBlank(str)) { return null; } // 去掉'|"|;|字元 str = StringUtil.replace(str, "'", ""); str = StringUtil.replace(str, """, ""); str = StringUtil.replace(str, ";", ""); str = StringUtil.replace(str, "\", ""); // 轉換成小寫 str = str.toLowerCase(); // 非法字元 String[] keywords = { "master", "truncate", "insert", "select", "delete", "update", "declare", "alert", "drop" }; // 判斷是否包含非法字元 for (String keyword : keywords) { if (str.indexOf(keyword) != -1) { throw new SysException("包含非法字元"); } } return str; } }
複雜的SQL分頁語句,需要自定義SQL的count語句如何實現呢?
PageHelper實現分頁,預設是查詢自定義的count語句是否存在,如果存在就用自定義的語句,否則就在外層包裝查詢的語句,而自定義count語句只需要在在查詢語句名稱後面新增_COUNT即可。例如
查詢集合的語句名稱為queryPageList
,那麼查詢count的語句為queryPageList_COUNT
,返回Long型別即可。
<select id="queryPageList_COUNT" resultType="java.lang.Long"> select count(1) from t_user u left join t_user_role ur on ur.userOid=u.oid <where> <if test="name != null">name=#{name}</if> </where> </select>
1.pageHelper分頁查詢有個特殊的要求,查詢下sql語句一定要緊跟在分頁查詢的後面,否則分頁查詢會失效。之前採用的如下寫法容易失效,建議採用java8的寫法
PageHelper.startPage(pagedList.getPageNum(),pagedList.getPageSize()); //緊跟分頁查詢後面 List<TUser> list = list(user); PageInfo<TUser> pageInfo =new PageInfo<>(list); return PageUtils.toPageList(pageInfo);
2.注意pagehelper的reasonable 預設為false,遇到查詢頁數大於總頁數時,出現分頁失敗
pagehelper的reasonable 預設為false,遇到查詢頁數大於總頁數時,查詢為空;當reasonable設定為true時,遇到查詢頁數大於總頁數時,查詢最後一頁資料;
3.PageHelper先開啟分頁,後對list資料操作將會導致分頁錯誤
範例程式碼:
public PageInfo<TUserVO> getUserPageList(int pageNum, int pageSize) { PageHelper.startPage(pageNum,pageSize); List<TUserVO> tUserVOsByView = userMapper.getUserList(); List<TUserVO> TUserVOs = new ArrayList<>(); for (TUserVO TUserVO : tUserVOsByView) { TUserVO TUserVOSingle = new TUserVO(); TUserVOSingle.setHdId(TUserVO.getHdId()); TUserVOs.add(TUserVOSingle); } PageInfo<TUserVO> pageViewInfo = new PageInfo<>(TUserVOs); return pageViewInfo; }
4.PageHelper先對list資料操作,後開啟分頁,將會導致分頁失效
範例程式碼:
public PageInfo<TUserVO> getUserPageList(int pageNum, int pageSize) { List<TUserVO> tUserVOsByView = userMapper.getUserList(); List<TUserVO> TUserVOs = new ArrayList<>(); for (TUserVO TUserVO : tUserVOsByView) { TUserVO TUserVOSingle = new TUserVO(); TUserVOSingle.setHdId(TUserVO.getHdId()); } PageHelper.startPage(pageNo,pageSize); PageInfo<TUserVO> pageViewInfo = new PageInfo<>(TUserVOs); return pageViewInfo; }
大家需要注意下,抽時間可以去驗證下結果。
PageHelper 對於大表查詢資料量越大,效能越差,這是因為PageHelper分頁是自動在sql語句後面拼接limit沒有進行相關的優化,一旦資料大,效能就比較慢。
例如:
優化前SQL語句:
SELECT d.* FROM tag_detail d LIMIT 10000000,10
查詢的時間大概需要10秒左右,執行速度比較慢。
優化後SQL語句:
SELECT d.* FROM tag_detail d INNER JOIN (SELECT oid FROM tag_detail LIMIT 10000000,10) t ON d.oid= t.oid;
子查詢先通過分頁查詢主鍵欄位,然後進行關聯查詢,經過優化後,查詢時間大概為1秒左右。效能大幅度提升。
本文講解了PageHelper的基本的使用和相關的問題,這些都是我從實際的專案中總結出來的問題以及相關的解決方案,大家在使用的時候要特別注意,不要放同樣的錯誤。
到此這篇關於Spring Boot 整合PageHelper的使用方法的文章就介紹到這了,更多相關Spring Boot 整合PageHelper內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45