PageHelper分页的那些坑,你中了几个?来我教你如何避坑

原创 不码不疯魔 不码不疯魔 2023-09-04 17:15 发表于四川

收录于合集

#分页插件1个

#PageHelper1个

#分页常见Bug1个

#高频面试题10个

20

23

不疯魔不成活,大家好呀,我是科哥,江湖ID 不码不疯魔

真实场景:分页在企业的实际项目中具有至关重要的意义。它可以帮助企业更高效地处理大量数据,提高用户体验,满足特定的业务需求,并确保系统的稳定运行。在Java开发中,理解并选择适合的分页技术对于实现成功的项目至关重要。

在MySQL中,常见的实现分页的方式有两种:

1. Limit语句:MySQL提供了Limit句来实现数据分页。该语法如下:

SELECT column(s) FROM table_name LIMIT offset, num;其中,offset为起始位置,num为返回行数;

2.存储过程或函数:除了语句外,还可以通过存储过程或函数来实现数据分页。在存储过程函数中定义一个游标(Cursor来遍历表中所有记录,并在每次返回指定数量的记录时终止游标并返回结果集;

此外,在业务开发也可能会使用到一些针对MySQL数据库的分页组件或框架,常见的包括:

1.MyBatis-PageHelper:MyBatis-PageHelper是一个为MyBatis提供物理分页支持的插件。它简化了开发者进行分页的流程,支持多种数据库,包括MySQL;

2.Spring Data JPA:Spring Data JPASpring框架下的一个子项目它基于JPA规范封装了一些常见数据访问功能。其中就包含了一些内置的分页方法;

3.Hibernate Query DSL:Hibernate DSL 是基于 Hibernate ORM 框架封装一套简单易用、类型安全、自然关联映射和JPA兼容性高的查询工具。它提供了非方便灵活且可扩展性强的查询方式,也支持分页查询;

这些MySQL分页组件或框架都能方便地帮助开发者实现数据分页功能。

重点掌握:MyBatis-PageHelper分页组件项目实践中,常常会遇到如下问题

1.分页性能问题由于 MyBatis-PageHelper 是通过在 SQL 执行前后动态修改 SQL 来实现分页功能,因此对于大量、高并发的场景,可能会导致性能瓶颈。在使用时需要注意优化;

2.查询语句复杂度问题:Myatis-PageHelper 对于复杂查询语句可能会出现一些问题。例如,在涉及子查询或多表关联查询等复杂况下,可能会无法正确生成分页查询语句

3版本兼容性问题:MyBatis-PageHelper 的不同版本间可能存在不兼容的情况。如果业务中使用了不同版本的 MyBatis-PageHelper,需要特别注意版本兼容

4. 分页编码问题:MyBatis-PageHelper 在处理中文字符集时可能会出现编码错误的情,导致分页结果不正确。需要在和应用程序中统一设置字符集编码格式来避免该问题

5. 文档资料失问题:MyBatis-PageHelper 官方文档、社区问等资源相对较少,在初次接触和使用时可能需要花费更多时间去查找相关资料并解决相关问题

    注意:大量干货文章,有具体的商业对接案例Word,记得关注,免费领取,标记星号每日更多干货分享哟!!!

 

01

常见坑点1

添加了PageHelper.startPage(currentPage,pageSize);方法。也没有正常分页。例如下面这段代码:

public RespResult<PageWrapperDTO<SysMenu>> findSysMenuListPage(Integer currentPage, Integer pageSize) {
    //使用分页插件
    PageHelper.startPage(currentPage,pageSize);
    // 根据角色ID查询角色信息,默认查出是null
    SysRole sysRole = sysRoleMapper.findSysRoleById(3);
    // 包装分页返回对象
    PageWrapperDTO<SysMenu> sysMenuPageWrapperDTO = new PageWrapperDTO<SysMenu>();
    //查询权限菜单数据
    List<SysMenu> sysMenus = sysMenuMapper.findSysMenuList();
    // 设置分页返回对象
    PageResultUtil.setPageResult(sysMenus,sysMenuPageWrapperDTO);
    return RespResult.success(sysMenuPageWrapperDTO);
}

原因分析:只对该语句以后的第一个查询(Select)语句得到的数据进行分页。上面这个代码,应该写成下面这个样子才能正常分页。

public RespResult<PageWrapperDTO<SysMenu>> findSysMenuListPage(Integer currentPage, Integer pageSize) {
    // 根据角色ID查询角色信息,默认查出是null
    SysRole sysRole = sysRoleMapper.findSysRoleById(3);
    //使用分页插件
    PageHelper.startPage(currentPage,pageSize);
    // 包装分页返回对象
    PageWrapperDTO<SysMenu> sysMenuPageWrapperDTO = new PageWrapperDTO<SysMenu>();
    //查询权限菜单数据
    List<SysMenu> sysMenus = sysMenuMapper.findSysMenuList();
    // 设置分页返回对象
    PageResultUtil.setPageResult(sysMenus,sysMenuPageWrapperDTO);
    return RespResult.success(sysMenuPageWrapperDTO);
}

02

常见坑点2

sysRoleMapper.findSysRoleById(3);莫名其妙的分页。例如下面这段代码:

public RespResult<PageWrapperDTO<SysMenu>> search(SysMenuSearchDTO sysMenuSearchDTO) {
    //使用分页插件
    PageHelper.startPage(1,5);
    // 包装分页返回对象
    PageWrapperDTO<SysMenu> sysMenuPageWrapperDTO = new PageWrapperDTO<SysMenu>();
    List<SysMenu> sysMenus = null;
    if(sysMenuSearchDTO != null){
        //查询权限菜单数据
        sysMenus = sysMenuMapper.findSysMenuByCondition(sysMenuSearchDTO.getId(),sysMenuSearchDTO.getTitle());
    }else{
        sysMenus = new ArrayList<>();
    }
    // 设置分页返回对象
    PageResultUtil.setPageResult(sysMenus,sysMenuPageWrapperDTO);
    // 根据角色ID查询角色信息,默认查出是null
    SysRole sysRole = sysRoleMapper.findSysRoleById(3);
    return RespResult.success(sysMenuPageWrapperDTO);
}

原因分析:这种情况下由于sysMenuSearchDTO 存在null的情况,就会导致pageHelper生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。上面这个代码,应该写成下面这个样子才能保证安全。

public RespResult<PageWrapperDTO<SysMenu>> search(SysMenuSearchDTO sysMenuSearchDTO) {
    // 包装分页返回对象
    PageWrapperDTO<SysMenu> sysMenuPageWrapperDTO = new PageWrapperDTO<SysMenu>();
    List<SysMenu> sysMenus = null;
    if(sysMenuSearchDTO != null){
        //使用分页插件
        PageHelper.startPage(1,5);
        //查询权限菜单数据
        sysMenus = sysMenuMapper.findSysMenuByCondition(sysMenuSearchDTO.getId(),sysMenuSearchDTO.getTitle());
    }else{
        sysMenus = new ArrayList<>();
    }
    // 设置分页返回对象
    PageResultUtil.setPageResult(sysMenus,sysMenuPageWrapperDTO);
    // 根据角色ID查询角色信息,默认查出是null
    SysRole sysRole = sysRoleMapper.findSysRoleById(3);
    return RespResult.success(sysMenuPageWrapperDTO);
}

03

PageHelper使用经验总结

1、确保PageHelper.startPage()方法和Dao或Mapper的方法中间没有其他业务逻辑处理,从而保证ThreadLocal里面的Page对象能够被正常清空。

2、增加日志过滤器,保证方法执行完成后当前线程的ThreadLocal里面的Page对象都被清空。

/**
 * 类描述: 日志过滤器
 */
public class LogFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //清空当前线程的ThreadLocal里面的Page对象
        clearPage();
    }
    public void clearPage(){
        //调用PageHelper清空当前线程的ThreadLocal里面的Page对象
        PageHelper.clearPage();
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }
}

收获

商业案例+文档资料

图片

商业案例+笔记文档,怎么获取?

点击下方公众号进入关注,后台回复【PageHelper】即可获取所有资料,大量的商用级方案已经更新,记得关注,免费领取,标记星号哟!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值