SpringMVCDemo中,遇到的问题(四) 之分页功能

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;
    }
}

 

 

猜你喜欢

转载自www.cnblogs.com/kunpengv5/p/10025069.html