前言
成都創(chuàng)新互聯(lián)是一家專(zhuān)注于做網(wǎng)站、網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),印江網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)10余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:印江等地區(qū)。印江做網(wǎng)站價(jià)格咨詢(xún):18982081108
在web開(kāi)發(fā)過(guò)程中涉及到表格時(shí),例如dataTable,就會(huì)產(chǎn)生分頁(yè)的需求,通常我們將分頁(yè)方式分為兩種:前端分頁(yè)和后端分頁(yè)。
前端分頁(yè)
一次性請(qǐng)求數(shù)據(jù)表格中的所有記錄(ajax),然后在前端緩存并且計(jì)算count和分頁(yè)邏輯,一般前端組件(例如dataTable)會(huì)提供分頁(yè)動(dòng)作。
特點(diǎn)是:簡(jiǎn)單,很適合小規(guī)模的web平臺(tái);當(dāng)數(shù)據(jù)量大的時(shí)候會(huì)產(chǎn)生性能問(wèn)題,在查詢(xún)和網(wǎng)絡(luò)傳輸?shù)臅r(shí)間會(huì)很長(zhǎng)。
后端分頁(yè)
在ajax請(qǐng)求中指定頁(yè)碼(pageNum)和每頁(yè)的大小(pageSize),后端查詢(xún)出當(dāng)頁(yè)的數(shù)據(jù)返回,前端只負(fù)責(zé)渲染。
特點(diǎn)是:復(fù)雜一些;性能瓶頸在MySQL的查詢(xún)性能,這個(gè)當(dāng)然可以調(diào)優(yōu)解決。一般來(lái)說(shuō),web開(kāi)發(fā)使用的是這種方式。
我們說(shuō)的也是后端分頁(yè)。
MySQL對(duì)分頁(yè)的支持
簡(jiǎn)單來(lái)說(shuō)MySQL對(duì)分頁(yè)的支持是通過(guò)limit子句。請(qǐng)看下面的例子。
limit關(guān)鍵字的用法是
LIMIT [offset,] rows
offset是相對(duì)于首行的偏移量(首行是0),rows是返回條數(shù)。
# 每頁(yè)10條記錄,取第一頁(yè),返回的是前10條記錄 select * from tableA limit 0,10; # 每頁(yè)10條記錄,取第二頁(yè),返回的是第11條記錄,到第20條記錄, select * from tableA limit 10,10;
這里提一嘴的是,MySQL在處理分頁(yè)的時(shí)候是這樣的:
limit 1000,10 - 過(guò)濾出1010條數(shù)據(jù),然后丟棄前1000條,保留10條。當(dāng)偏移量大的時(shí)候,性能會(huì)有所下降。
limit 100000,10 - 會(huì)過(guò)濾10w+10條數(shù)據(jù),然后丟棄前10w條。如果在分頁(yè)中發(fā)現(xiàn)了性能問(wèn)題,可以根據(jù)這個(gè)思路調(diào)優(yōu)。
Mybatis分頁(yè)插件PageHelper
在使用Java Spring開(kāi)發(fā)的時(shí)候,Mybatis算是對(duì)數(shù)據(jù)庫(kù)操作的利器了。不過(guò)在處理分頁(yè)的時(shí)候,Mybatis并沒(méi)有什么特別的方法,一般需要自己去寫(xiě)limit子句實(shí)現(xiàn),成本較高。好在有個(gè)PageHelper插件。
1、POM依賴(lài)
Mybatis的配置就不多提了。PageHelper的依賴(lài)如下。需要新的版本可以去maven上自行選擇
com.github.pagehelper pagehelper 4.1.4
2、Mybatis對(duì)PageHelper的配置
打開(kāi)Mybatis配置文件,一般在Resource路徑下。我這里叫mybatis-config.xml。
<?xml version="1.0" encoding="UTF-8"?>
這里要注意的是PageHelper相關(guān)的配置。
如果你沒(méi)有加載Mybatis配置文件,那么使用的是Mybatis默認(rèn)的配置。如何加載Mybatis配置文件呢?
到你的dataSrouce配置中。
在配置sqlSessionFactory的時(shí)候,指定Mybatis核心配置文件和mapper的路徑,代碼如下
@Bean(name = "moonlightSqlSessionFactory") @Primary public SqlSessionFactory moonlightSqlSessionFactory(@Qualifier("moonlightData") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis-mapper/*.xml")); bean.setConfigLocation(new ClassPathResource("mybatis-config.xml")); return bean.getObject(); }
說(shuō)明:
這里配置的mapper.xml存放路徑,在Resource/mybatis-mapper文件夾下
這里配置的mybatis-config.xml文件,在Resource/下
3、分頁(yè)
準(zhǔn)備一個(gè)mapper.xml,測(cè)試就隨便寫(xiě)一個(gè)吧,干脆就用工程里的一個(gè)。
這里這個(gè)查詢(xún),是一個(gè)典型的多條件查詢(xún),我們要做的是對(duì)多條件匹配到的記錄進(jìn)行分頁(yè)。
<?xml version="1.0" encoding="UTF-8"?>id, name, type, `group`, geo, createTime, updateTime
在Mapper.java接口中編寫(xiě)對(duì)應(yīng)的方法
ListqueryGeoFence(GeoFenceQueryParam geoFenceQueryParam);
先上分頁(yè)代碼,后面再說(shuō)明
@RequestMapping(value = "/fence/query", method = RequestMethod.POST) @ResponseBody public Response queryFence(@RequestBody GeoFenceQueryParam geoFenceQueryParam) { try { Integer pageNum = geoFenceQueryParam.getPageNum()!=null?geoFenceQueryParam.getPageNum():1; Integer pageSize = geoFenceQueryParam.getPageSize()!=null?geoFenceQueryParam.getPageSize():10; PageHelper.startPage(pageNum, pageSize); Listlist = moonlightMapper.queryGeoFence(geoFenceQueryParam); return new Response(ResultCode.SUCCESS, "查詢(xún)geoFence成功", list); } catch (Exception e) { logger.error("查詢(xún)geoFence失敗", e); return new Response(ResultCode.EXCEPTION, "查詢(xún)geoFence失敗", null); } }
說(shuō)明:
1、PageHelper的優(yōu)點(diǎn)是,分頁(yè)和Mapper.xml完全解耦。實(shí)現(xiàn)方式是以插件的形式,對(duì)Mybatis執(zhí)行的流程進(jìn)行了強(qiáng)化,添加了總數(shù)count和limit查詢(xún)。屬于物理分頁(yè)。
2、有一個(gè)安全性問(wèn)題,需要注意一下,不然可能導(dǎo)致分頁(yè)錯(cuò)亂。我這里直接粘貼了這篇博客里的一段話。
4. 什么時(shí)候會(huì)導(dǎo)致不安全的分頁(yè)?
PageHelper 方法使用了靜態(tài)的 ThreadLocal 參數(shù),分頁(yè)參數(shù)和線程是綁定的。
只要你可以保證在 PageHelper 方法調(diào)用后緊跟 MyBatis 查詢(xún)方法,這就是安全的。因?yàn)?PageHelper 在 finally 代碼段中自動(dòng)清除了 ThreadLocal 存儲(chǔ)的對(duì)象。
如果代碼在進(jìn)入 Executor 前發(fā)生異常,就會(huì)導(dǎo)致線程不可用,這屬于人為的 Bug(例如接口方法和 XML 中的不匹配,導(dǎo)致找不到 MappedStatement 時(shí)), 這種情況由于線程不可用,也不會(huì)導(dǎo)致 ThreadLocal 參數(shù)被錯(cuò)誤的使用。
但是如果你寫(xiě)出下面這樣的代碼,就是不安全的用法:
PageHelper.startPage(1, 10); Listlist; if(param1 != null){ list = countryMapper.selectIf(param1); } else { list = new ArrayList (); }
這種情況下由于 param1 存在 null 的情況,就會(huì)導(dǎo)致 PageHelper 生產(chǎn)了一個(gè)分頁(yè)參數(shù),但是沒(méi)有被消費(fèi),這個(gè)參數(shù)就會(huì)一直保留在這個(gè)線程上。當(dāng)這個(gè)線程再次被使用時(shí),就可能導(dǎo)致不該分頁(yè)的方法去消費(fèi)這個(gè)分頁(yè)參數(shù),這就產(chǎn)生了莫名其妙的分頁(yè)。
上面這個(gè)代碼,應(yīng)該寫(xiě)成下面這個(gè)樣子:
Listlist; if(param1 != null){ PageHelper.startPage(1, 10); list = countryMapper.selectIf(param1); } else { list = new ArrayList (); }
這種寫(xiě)法就能保證安全。
如果你對(duì)此不放心,你可以手動(dòng)清理 ThreadLocal 存儲(chǔ)的分頁(yè)參數(shù),可以像下面這樣使用:
Listlist; if(param1 != null){ PageHelper.startPage(1, 10); try{ list = countryMapper.selectAll(); } finally { PageHelper.clearPage(); } } else { list = new ArrayList (); }
這么寫(xiě)很不好看,而且沒(méi)有必要。
總結(jié)
以上所述是小編給大家介紹的Mybatis分頁(yè)插件PageHelper的配置和簡(jiǎn)單使用方法(推薦),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!