ssm+gradle+generator下PageHelper的使用与分页结果错误问题的解决

1、build.gradle配置

compile group: 'com.github.pagehelper', name: 'pagehelper', version: '5.1.4'

2、首先在spring-mybatis中配置pagehelper

<!--配置mybatis的sqlSession-->
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"
          scope="prototype">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dynamicDataSource"/>
        <property name="configLocation" value="classpath:sqlMapConfig.xml"/>
        <property name="plugins">
            <array>
                <bean class="com.github.pagehelper.PageInterceptor">
                    <property name="properties">
                        <value>
                            helperDialect=mysql
                            reasonable=true
                        </value>
                    </property>
                </bean>
            </array>
        </property>
    </bean>

3、分页实例

@Override
    public PagingResult getPageList(int pageNum, int pageSize) {
        //设置分页参数
        Page page = PageHelper.startPage(pageNum, pageSize, true);

        List<SysHospitalization> list = sysHospitalizationDao.selectAll();
        if (list.size() == 0) {
            throw new NoneGetException("没有查询到用户相关记录!");
        }

        //获取分页之后的信息
        PagingResult pagingResult = new PagingResult((int) page.getTotal(), list);
        return pagingResult;
    }

4、PageHelper的原理

MySQL对分页的支持

简单来说MySQL对分页的支持是通过limit子句。请看下面的例子。

limit关键字的用法是
LIMIT [offset,] rows
offset是相对于首行的偏移量(首行是0),rows是返回条数。

# 每页10条记录,取第一页,返回的是前10条记录
select * from tableA limit 0,10;
# 每页10条记录,取第二页,返回的是第11条记录,到第20条记录,
select * from tableA limit 10,10;

这里提一嘴的是,MySQL在处理分页的时候是这样的:
limit 1000,10 - 过滤出1010条数据,然后丢弃前1000条,保留10条。当偏移量大的时候,性能会有所下降。

limit 100000,10 - 会过滤10w+10条数据,然后丢弃前10w条。如果在分页中发现了性能问题,可以根据这个思路调优。

Mybatis分页插件PageHelper

在使用Java Spring开发的时候,Mybatis算是对数据库操作的利器了。不过在处理分页的时候,Mybatis并没有什么特别的方法,一般需要自己去写limit子句实现,成本较高。好在有个PageHelper插件。
详见 https://www.cnblogs.com/kangoroo/p/7998433.html

5、分页结果错误可能的原因

1、在PageHelper.startPage(request.getPageNum(), request.getPageSize());后面紧跟第一条SQL才会被分页(startPage与SQL中间不能有别的代码),且是线程安全的
什么是第一句sql语句?
错误案例:

@Override
    public PagingResult getList222(SysSurgeryQuery sysSurgeryQuery,int pageNum, int pageSize, String sort, String sortOrder) {
        List<SysSurgery> list = sysSurgeryDao.selectByExample(getExample(sysSurgeryQuery));
        if (list != null && list.size() > 0) {
            //设置分页参数:在这之后的第一句sql语句才会被分页
            Page page = PageHelper.startPage(pageNum, pageSize, true);
            //这句是第一个sql语句吗?不是
            //跟踪getSysSurgeryDTOS(list),会发现其中的getSysSurgeryDTO(item)
            //里有个getAreaStr(int area),这里执行了sql语句,
            //所以进行分页的不是resultList,而是首次执行getAreaStr(int area)
            //得到的值。
            //如果 Page page = PageHelper.startPage(pageNum, pageSize, true);
            //这行代码放在
            //List<SysSurgery> list = sysSurgeryDao.selectByExample(getExample(sysSurgeryQuery));
            //之后,则会正确分页
            //注意:List<SysSurgery> list = sysSurgeryDao.selectByExample(getExample(sysSurgeryQuery));
            //后不能加筛选条件
            //.stream().filter(item->item.gethArea()==1).collect(Collectors.toList())
            //因为是对.stream之前的数据分页,不会对筛选之后的数据分页。
            List<SysSurgeryDTO> resultList = getSysSurgeryDTOS(list);
            PagingResult pagingResult = new PagingResult((int) page.getTotal(), resultList);
            return pagingResult;
        }
        throw new NoneGetException("没有查询到手术相关记录!");
    }

    private List<SysSurgeryDTO> getSysSurgeryDTOS(List<SysSurgery> list) {
        List<SysSurgeryDTO> resultList = new ArrayList<>();
        for (SysSurgery item : list) {
            SysSurgeryDTO sysSurgeryDTO = getSysSurgeryDTO(item);
            resultList.add(sysSurgeryDTO);
        }
        return resultList;
    }

    private SysSurgeryDTO getSysSurgeryDTO(SysSurgery result) {
        SysSurgeryDTO sysSurgeryDTO = convertToSysSurgeryDTO(result);
        sysSurgeryDTO.sethAreaStr(getAreaStr(result.gethArea()));
        sysSurgeryDTO.setSurgeryStatusStr(getSurgeryStatusStr(result.getSurgeryStatus()));
        sysSurgeryDTO.setSurgeryDatetime(getDateStr(result.getSurgeryDatetime()));
        return sysSurgeryDTO;
    }

    private String getAreaStr(int area) {
        SysArea sysArea = sysAreaService.get(area);
        if (sysArea == null) {
            throw new NoneGetException("病区号:" + area + "在sys_area表中不存在!");
        }
        return sysArea.getValue();
    }

参考 https://blog.csdn.net/qq_33315102/article/details/80572566

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值