pagehelper分页插件springboot中使用

本文主要讨论了在SpringBoot项目中使用PageHelper进行分页时遇到的问题,特别是在处理线程池和ThreadLocal时可能导致的异常。文章提供了两种解决方案:一是通过实现HandlerInterceptor清理ThreadLocal中的page参数,二是利用try-with-resources自动管理资源以避免问题。
摘要由CSDN通过智能技术生成

添加依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.5</version>
</dependency>

配置文件

pagehelper:
# helper-dialect:指定数据库,不指定的话会默认自动检测数据库类型
  helper-dialect: mysql
  # reasonable:是否启用分页合理化。如果启用,当pagenum<1时,会自动查询第一页的数据,当pagenum>pages时,自动查询最后一页数据;不启用的,以上两种情况都会返回空数据
  reasonable: false
  # support-methods-arguments:默认值false,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。(如果参数中有pageNum,pageSize分页参数,则会自动分页)
  support-methods-arguments: false
  # params:用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
  params: count=countsql

方法使用

//方法一:使用service查询到的结果存储在request域中

private void selectAllUsers(HttpServletRequest request, HttpServletResponse response){
        Page<Person> page=PageHelper.startPage(Integer.parseInt(num),5);  
        //通过userService获取user的信息,其sql语句为"select * from user" 但因pagehelp已经注册为插件,所以pagehelp会在原sql语句上增加limit,从而实现分页
        List<Person> persons=userService.getAllUsersBypageHelper();
        //获取页面信息的对象,里面封装了许多页面的信息 如:总条数,当前页码,需显示的导航页等等  
        PageInfo<Person> pageHelper=page.toPageInfo(); 
    }

//方法二:使用service查询到的结果存储在自定义的类中然后返回给前端
 public PageInfo<ProjectListVO> queryByProjectName(Integer pageNo, Integer pageSize, String projectName) {
        PageResult<List<ProjectListVO>> result = new PageResult<>();
        try {
            PageHelper.startPage(pageNo, pageSize);
            //设置完上边的PageHelper之后查询的时候,查询语句会自动加入 limits startpage   count,查询结果就是正确的结果
            List<ProjectListVO> projectVOList = projectMapper.queryByProjectName(projectName); 
            //获取页面信息的对象,里面封装了许多页面的信息 如:总条数,当前页码,需显示的导航页等等
            PageInfo<ProjectListVO> pageInfo = new PageInfo<>(projectVOList);
        } finally {
            PageHelper.clearPage();
        }
        return result;
    }

PageHelper.clearPage()

PageHelper 是较为常用的分页插件,通过实现 Mybatis 的 Interceptor 接口完成对 query sql 的动态分页,其中分页参数由
ThreadLocal进行保存,threadlocal而是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据.

简单的 分页执行过程:

  1. 设置 page 参数
  2. 执行 query 方法
  3. Interceptor 接口 中校验 ThreadLocal 中是否存在有设置的 page 参数
  4. 存在 page 参数,重新生成 count sql 和 page sql,并执行查询。不存在 page 参数,直接返回 查询结果
  5. 执行 LOCAL_PAGE.remove() 清除 page 参数 threadlocal

这里就存在一个问题了
观察上述的执行过程,可以发现,如果在第 1 步和第 2 步 之间发生异常,那么 LOCAL_PAGE 中当前线程对应的 page 参数并不会 remove。

在不使用线程池的情况下,当前线程在执行完毕后会被销毁,这时 当前线程 中的 threadLocals 参数 将会被情况,也就清空 了
LOCAL_PAGE 中 当前线程的 page 参数。

但是如果使用了线程池,当前线程执行完毕,并不会被销毁,而是会将当前线程再次存放到池中,标记为空闲状态,以便后续使用。在后续使用这个线程的时候,由于
线程 的 threadLocals 依旧存在有值,尽管我们在第 1 步时未设置 page 参数,第 3 步 的也能获取到page参数,从而生成 count sql 和
page sql,从而影响我们的正常查询我。

另外SpringBoot 项目中会使用内置的 Tomcat 作为服务器,而Tomcat会默认使用线程来处理请求,从而便引发了上述问题

解决方案1,在每次使用完分页语句后执行pagehelper.clearpage()如上demo所示,但是这样比较麻烦
我们可以实现 HandlerInterceptor , WebRequestInterceptor 对 request 请求的拦截器,清理我们localthread里的page

@Component
public class UrlInterceptor implements HandlerInterceptor, WebMvcConfigurer {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        PageHelper.clearPage();
        return true;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this).addPathPatterns("/**");
    }
}

解决方案2,使用try-with-resources语句,这是JDK1.7的新特性,
Java 7增强了try语句的功能——它允许在try关键字后跟一对圆括号,圆括号可以声明,初始化一个或多个资源,此处的资源指得是那些必须在程序结束时必须关闭的资源(比如数据库连接,网络连接等)
只要这些资源实现类实现了Closeable或AutoCloseable接口,就可以自动关闭。

注意:如果try()里面有两个资源,用逗号分开,资源的close方法的调用顺序与它们的创建顺序相反。

//方法一
private void selectAllUsers(HttpServletRequest request, HttpServletResponse response) {
    try (Page<Person> page = PageHelper.startPage(Integer.parseInt(num), 5)) {
        //通过userService获取user的信息,其sql语句为"select * from user" 但因PageHelp已经注册为插件,所以pagehelp会在原sql语句上增加limit,从而实现分页
        List<Person> persons = userService.getAllUsersBypageHelper();
        //获取页面信息的对象,里面封装了许多页面的信息 如:总条数,当前页码,需显示的导航页等等  
        PageInfo<Person> pageHelper = page.toPageInfo();
    }
}

//方法二:使用service查询到的结果存储在自定义的类中然后返回给前端
public PageInfo<ProjectListVO> queryByProjectName(Integer pageNo, Integer pageSize, String projectName) {
    PageResult<List<ProjectListVO>> result = new PageResult<>();
    try (PageHelper.startPage(pageNo, pageSize)) {
        //设置完上边的PageHelper之后查询的时候,查询语句会自动加入 limits startpage   count,查询结果就是正确的结果
        List<ProjectListVO> projectVOList = projectMapper.queryByProjectName(projectName);
        //获取页面信息的对象,里面封装了许多页面的信息 如:总条数,当前页码,需显示的导航页等等
        PageInfo<ProjectListVO> pageInfo = new PageInfo<>(projectVOList);
    }
    return result;
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot项目集成PageHelper分页插件的步骤如下: 1. 打开Maven库,找到com.github.pagehelper:pagehelper-spring-boot-starter。 2. 确定需要使用的版本号,比如1.4.1。 3. 在项目的pom.xml文件添加PageHelper的依赖。可以使用如下代码: ``` <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.1</version> </dependency> ``` 4. 在application.properties或application.yml配置文件进行配置,添加以下属性: ``` # 开启分页支持 pagehelper.helper-dialect=mysql pagehelper.reasonable=true pagehelper.support-methods-arguments=true pagehelper.params=count=countSql ``` 这里的配置是针对MySQL数据库的,如果你使用的是其他数据库,需要根据对应的数据库类型进行配置。 5. 在需要分页的Mapper方法上使用PageHelper.startPage方法来开启分页功能。例如: ``` @Mapper public interface UserMapper { List<User> getUsers(); } ``` 在UserMapper接口的方法上加上注解@Select,并在方法内部使用PageHelper.startPage方法开启分页,如下所示: ``` @Select("SELECT * FROM user") List<User> getUsers(); ``` 6. 运行项目,分页功能就会生效。 通过以上步骤,你就可以在Spring Boot项目成功集成PageHelper分页插件了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [springboot整合分页插件PageHelper](https://blog.csdn.net/weixin_42408447/article/details/117528795)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Springboot集成pagehelper 分页插件](https://blog.csdn.net/weixin_58696998/article/details/124397756)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值