SpringMVC+MyBatis学习Pagehelper——实现分页功能

首先记录的是在任务中遇到的问题,使用PageHelper只是其中的一方面(最后并没有用),所以想深入学习PageHelper的童鞋可以移步到其他博客啦~
在这里提供两个链接:
PageHelper的GitHub地址
别人写的一个PageHelper分页查询方法


下面开始从头到尾记录下任务中的问题和我的解决方法

需要实现的功能:

主要目的是查询数据,返回的是给定的日期中,不同条件下的数据及日环比。即:
(1)给定日期( startDate 2018-08-01 endDate 2018-08-20 )
(2)给定其他查询参数(bucket、business、platform等)
查询满足给定的条件下的数据(PV、UV、ClickPV、ClickUV)及日环比(2018-08-01 PV PVChange)

发现问题

需要从MySQL查找数据量较大,从查找到显示用时较长。有两方面原因:
(1)查找数据时间较短,但前端显示加载时间较长。导致这个问题出现的原因就是返回数据量大,这种情况使用分页功能,返回给定页面的数据比较合适。
(2)在MyBaits中计算变化时耗时较长。最好是只在SQL中进行数据的查询,返回结果后在Impl中进行日环比等变化数据的计算。

解决步骤一:

方法:使用MySQL的limit分页查询

代码格式:

limit (pageNumber-1)*pageSize, pageSize

查询数据实际代码:

select dt, (a.pv, a.pv-b.pv)/b.pv as change 
from(
    select dt, pv
    from table
    where dt between #{a} and #{b} and xx = #{xx} and xx = #{xx}
) a
left outer join(
    select dt, pv
    from table
    where dt between DATE_SUB(#{a},INTERVAL 1 day) and DATE_SUB(#{b},INTERVAL 1 day) and xx = #{xx} and xx = #{xx}
) b
on a.dt = b.dt and a.xx = b.xx
order by dt, xx, xx
<if test = "offset >= 0 and pSize >= 0">
    limit #{offset}, #{pSize}
if>

使用 #{offset} 的原因是好像不支持代码中直接计算 offset 值,所以我在Service层计算出 offset 值 offset = (pageNumber - 1) * pageSize
使用 条件的原因是查询满足条件的记录数是不应该限定分页条件,这样在调用DAO的查询条目数方法时直接传入 -1,-1即可

查询满足要求数据记录条目数

select count(1)
from(
  xxxxxxxxxxxxx
)a

解决步骤二:

可以明显的看出在步骤一中查询数据的条目数和查询数据使用了相同的代码,xml文件中代码大量冗余,重复执行针对方法一的问题,网上有不少解决方法,其中SpringMVC提供了 PageHelper 分页插件。下面简单说一下使用方法:

  1. 首先在项目中添加PageHelper的Maven依赖
<dependency>
  <groupId>com.github.pagehelpergroupId>
  <artifactId>pagehelperartifactId>
  <version>4.1.6version>
dependency>
  1. 在已经配置好的mybatis配置文件中添加对 PageHelper 插件的属性配置
id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">
        <property name = "dataSource" ref = "dataSource"/>
        <property name = "configLocation" value = "classpath:/mybatis/mybatis-config.xml"/>
        <property name = "mapperLocations" value = "classpath:/mappers/*.xml"/>
        <property name = "plugins">
            
                class = "com.github.pagehelper.PageHelper">
                    <property name = "properties">
                        
                            dialet = mysql
                            rowBoundsWithCount = true
                        
                    property>
                
            
        property>
    
  1. 在Service层中直接调用
PageHelper.startPage(pageNum, pageSize);
PageHelper.orderBy("dt asc");
List list = xxxDao.getOrderData(xxx,xxx,xxx);
PageInfo pageInfo = new PageInfo(list);
int allSize = pageInfo.getTotal();  //返回总记录条数
List<> res = pageInfo.getList();    //返回分页记录

解决步骤三:

在使用了上述的方法后发现,还是有部分页面加载时间过长。导致这个问题出现的原因就是执行DAO方法(SQL查询语句)时间过长,解决方法如上所述:SQL只负责查数据,返回的数据在Service层中进行处理。

所以,查询语句变成了

select dt, pv, "0" as change 
-- 因为resultMap规定好了,所以还是要添加上change字段
from table
order by dt, xx, xx

因为我们需要计算日环比,所以在查询日期时要用一天前作为startDate。注意到因为我们查询的日期发生变化,所以在这里进行分页操作会使数据缺失,所以分页操作放到计算日环比时进行。

解决步骤四:

在接收到MyBatis传回来的数据后需要对其进行处理:计算变化及分页。
首先对数据进行预处理:

  1. 传回来的数据包括查找日期之外的“脏数据”吗,所以遍历数据时判断该条数据的日期是否满足条件,不满足则应该 continue 尽心下一条数据的判断
  2. 因为有了分页,所以为了加快返回速度,我们也不需要对查询页之外数据进行计算,给定一个 dataCount 变量,记录给定日期下遍历过的数据条数,当该变量在[ offset - 1,offset+pageSize]区间内时才需要进行计算。

在进行日期和其他条件的判断时用到了Java的日期和反射相关概念,用于计算给定数据日期的前一天/七天/一年;以及找到给定数据的列字段(因为返回数据格式有多种,无法给定具体的数据列字段)

在计算日环比时要注意:上一天的数据不应该仅仅满足 dt = 前一天,还要满足其他数据列数值相同(就是SQL中的 where)

结论

在进行完上述操作后,从点击到显示的速度大大提高。

                                  level+1

最大的教训就是:写逻辑前一定要想清楚啊。。。

你可能感兴趣的:(其他的小东西,MySQL)