SpringMVCDemo中,遇到的問題(四) 之分頁功能
阿新 • • 發佈:2018-11-27
1、背景:
線上經常出現因為研發程式碼編寫不規範,sql語句全表查詢,資料過多,硬生生把記憶體塞爆不斷GC,整個服務宕掉的情況。
引發這種場景的原因之一,歸咎在使用mybatis編寫sql語句時使用了萬能查詢語句。where 1=1之後,拼接的if條件都不符合條件。如下:
如果下面sql語句中,if條件都匹配不上,最後會執行 select * from retailer where 1=1
1 <!--sql片段--> 2 <sql id="query_retailer_where"> 3 <if test="name!=null">and name like '%${name}%'</if> 4 <if test="address!=null">and address like '%${address}%'</if> 5 <if test="status!=null">and status like '%${status}%'</if> 6 <if test="telphone!=null">and telphone = #{telphone}</if> 7 <if test="createtime!=null"> 8 and createtime = DATE_FORMAT(#{createtime},'%Y-%m-%d %H:%i:%S') 9 </if> 10 <if test="starttime != null"> <![CDATA[ and createtime >= to_date(#{starttime},'yyyy-MM-dd HH:mm:ss')]]></if> 11 <if test="endtime != null"> <![CDATA[ and createtime <= to_date(#{endtime},'yyyy-MM-dd HH:mm:ss')]]></if> 12 </sql> 13 14 <!--查詢--> 15 <select id="find" resultMap="resultMap" parameterType="java.util.Map"> 16 select * from retailer 17 where 1=1 18 <include refid="query_retailer_where"></include> 19 <if test="startPage != null and pageSize !=null"> 20 order by createtime desc 21 -- LIMIT #{startPage},#{pageSize} 22 </if> 23 </select>
這類場景的解決辦法,
一種是使用<choose></choose>,如果匹配不到就查詢不到,或查詢個預設範圍。
<where> <choose> <when> </when> <otherwise> AND 1=0 </otherwise>
</choose>
</where>
另外一種就是使用分頁查詢,引入Limit,限制查詢出的資料條數。
2、使用思路:
<!--查詢--> <select id="find" resultMap="resultMap" parameterType="java.util.Map"> select * from retailer where 1=1 <include refid="query_retailer_where"></include> <if test="startPage != null and pageSize !=null"> order by createtime desc LIMIT #{startPage},#{pageSize} </if> </select>
由底向上的思路,從limit的使用,來考慮一下傳值的邏輯。
limit的語法是,select * from table where ... limit start,size;
start:從第幾條記錄開始。
size : 讀取幾條記錄。
首先需要知道,從第幾條[下標]開始讀,要往後讀取多少條。
即分頁顯示的話,需要傳給sql語句兩個引數,某一頁面中第一條在表中的下標,以及頁面中資料的條數。
size好說,預設指定一個,或者從前臺輸入後取一個。
start下標,
一種方式是,前端js計算完,直接傳值過來。不涉及sql語句的計算。
另一種方式是,前端傳過來要跳轉到的頁碼,後臺sql中加入(pageNum-1)*size的計算,即為對應頁面的start下標值。
3、實現:
以第一種為例。
1)編寫分頁查詢的PageEntity類,首次查詢列表,需要給定個預設值。
/** * 分頁類,包含三個屬性 * 開始頁面、起始資料位置、每頁要取的資料 */ public class PageEntity { //當前頁 private Integer currentPage; //起始頁 private Integer startPage; //頁面的資料大小 private Integer pageSize; public Integer getCurrentPage() { if(currentPage==null){ currentPage = 1; } return currentPage; } public void setCurrentPage(Integer currentPage) { this.currentPage = currentPage; } public Integer getStartPage() { if (startPage==null){ startPage=0; } return startPage; } public void setStartPage(Integer startPage) { this.startPage = startPage; } public Integer getPageSize() { if (pageSize==null){ pageSize=5; } return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } }