项目实战--Spring Boot与PageHelper的集成及线程污染解决

一、PageHelper使用背景

公司要做个简单管理系统,要我搭建Spring Boot+MyBatis+PageHelper+Redis的项目框架然后交i给实习生来开发。这个其实很简单,但是遇到搭建和使用过程中PageHelper有好多小坑,就记录一下,避免再踩。
版本选择:

JDK 8
SpringBoot 2.5.0
MyBatis 3.5.7
PageHelper 5.2.0
二、步骤
2.1 新建Spring Boot项目

如果过程中,选择java版本时发现没有java8版本,只有java17和java21
在这里插入图片描述
原因:

spring2.X版本在20231124日停止维护,因此创建spring项目时不再有2.X版本的选项,只能从3.1.X版本开始选择
而Spring3.X版本不支持JDK8,JDK11,最低支持JDK17,因此JDK11也无法选择

解决:
目前阿里云支持创建Spring2.X版本的项目

修改Server URL为:https://start.aliyun.com

在这里插入图片描述
这样就可以创建啦

2.2 引入依赖

在pom.xml文件中添加相关依赖:

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- MyBatis Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>
    <!-- PageHelper -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.4.0</version>
    </dependency>
</dependencies>
2.3 配置PageHelper

在application.yml文件中进行PageHelper的基本配置:

pagehelper:
  helper-dialect: mysql # 指定数据库方言为MySQL
  reasonable: true # 分页合理化,启用后如果页码<1则查询第一页,页码>总页数则查询最后一页。
  support-methods-arguments: true # 支持通过Mapper接口参数来传递分页参数
  params: count=countSql # 指定count查询的参数名称
2.4 配置MyBatis

让PageHelper与MyBatis集成,还需在SpringBoot配置文件中添加MyBatis的相关配置:

mybatis:
  mapper-locations: classpath:/mappers/*.xml # Mapper XML文件的位置
  type-aliases-package: com.example.demo.entity # 实体类的包路径
2.5 编写Mapper接口和XML

User实体类:

public class User {
    private Long id;
    private String name;
    private String email;
    // getters and setters
}

对应的Mapper接口:

public interface UserMapper {
    @Select("SELECT * FROM users")
    List<User> selectAll();
}

Mapper XML文件则包含分页查询的SQL:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="selectAll" resultType="com.example.demo.entity.User">
        SELECT * FROM users
    </select>
</mapper>
2.6 使用PageHelper进行分页

Service层使用PageHelper进行分页查询:


@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    public PageInfo<User> getUsers(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> users = userMapper.selectAll();
        return new PageInfo<>(users);
    }
}

在Controller层,通过RESTful接口来调用分页查询:


@RestController
@RequestMapping("/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping
    public PageInfo<User> getUsers(@RequestParam(defaultValue = "1") int pageNum,
                                   @RequestParam(defaultValue = "10") int pageSize) {
        return userService.getUsers(pageNum, pageSize);
    }
}

这就实现简单的分页查询功能,通过PageHelper来控制分页参数。

三、问题解决

(1)分页无效或查询结果为空

确保在调用分页查询方法前,已经正确调用了PageHelper.startPage方法。
检查数据库连接是否正常,SQL查询语句是否正确。

(2)分页参数不生效

检查Controller层是否正确接收并传递分页参数。
确保application.yml中配置的support-methods-arguments为true

(3)性能问题

对于大数据量的表,分页查询可能会带来性能问题。可以通过增加索引、优化SQL查询等方式提高性能。

(4)使用过程中线程污染,无缘故的分页
前端调用一个未分页的接口,出现数据丢失或者报错的情况:
现象:前端调用一个只查询一条数据的接口,该接口执行的SQL是:

select id,statistics_month,update_time from business_statistics_record
order by statistics_month desclimit 1

在这里插入图片描述
但是实际上,日记打印出来的SQL:limit 1 limit ?, ?;就出现查询异常:
在这里插入图片描述
经过排查,真正原因是因为调用自定义分页出现问题:PageHelper.startPage(pageNum, pageSize);调用之后并没有消费,分页参数一直保存在线程中,当这个线程再次调用的时候,导致莫名奇妙的加上limit关键字。
查看PageHelper源码看到:

PageHelper 方法使用静态的 ThreadLocal参数,分页参数和线程是绑定的。只要保证在 PageHelper方法调用后紧跟MyBatis查询方法,这就是安全的。因为 PageHelper在finally代码段中自动清除ThreadLocal存储的对象。

而随机加上limit关键字,查看ThreadLocal LOCAL_PAGE值的变化,只有当线程复用的时候才会出现LOCAL_PAGE已被实例化。
在这里插入图片描述
为避免使用PageHelper过程中如果出现无缘无故出现分页,
在使用了PageHelper.startPage()后需要紧接着 MyBatis 查询方法。
最好是在执行sql的方法加上finally语句清理page缓存:
在这里插入图片描述

这个afterAll()方法中:
在这里插入图片描述
而 clearPage()方法的功能是:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/777333.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

hdu物联网硬件实验2 GPIO亮灯

学院 班级 学号 姓名 日期 成绩 实验题目 GPIO亮灯 实验目的 点亮三个灯闪烁频率为一秒 硬件原理 无 关键代码及注释 const int ledPin1 GREEN_LED; // the number of the LED pin const int ledPin2 YELLOW_LED; const int ledPin3 RED…

Java - JDK17语法新增特性(如果想知道Java - JDK17语法新增常见的特性的知识点,那么只看这一篇就足够了!)

前言&#xff1a;Java在2021年发布了最新的长期支持版本&#xff1a;JDK 17。这个版本引入了许多新的语法特性&#xff0c;提升了开发效率和代码可读性。本文将简要介绍一些常见的新特性&#xff0c;帮助开发者快速掌握并应用于实际开发中。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨…

Mysql笔记-v2【7月5日更新】

零、 help、\h、? 调出帮助 mysql> \hFor information about MySQL products and services, visit:http://www.mysql.com/ For developer information, including the MySQL Reference Manual, visit:http://dev.mysql.com/ To buy MySQL Enterprise support, training, …

深入分析 Android BroadcastReceiver (八)

文章目录 深入分析 Android BroadcastReceiver (八)1. 系统与自定义实现1.1 系统广播机制1.1.1 系统广播的实现原理1.1.2 系统广播的源码分析 1.2 自定义广播机制1.2.1 自定义广播的实现步骤1.2.2 自定义广播的源码分析 2. 广播机制设计的初衷与优势2.1 设计初衷2.2 优势 3. 总…

一文读懂轻量日志收集系统Loki工作原理

Loki 是由 Grafana Labs 开发的日志聚合系统&#xff0c;设计目标是提供一种高效、低成本的日志收集和查询解决方案。与传统的日志系统&#xff08;如 ELK Stack&#xff09;不同&#xff0c;Loki 不会对日志内容进行索引&#xff0c;而是仅对日志的元数据进行索引&#xff0c;…

Python数据分析案例49——基于机器学习的垃圾邮件分类系统构建(朴素贝叶斯,支持向量机)

案例背景 trec06c是非常经典的邮件分类的数据&#xff0c;还是难能可贵的中文数据集。 这个数据集从一堆txt压缩包里面提取出来整理为excel文件还真不容不易&#xff0c;肯定要做一下文本分类。 虽然现在文本分类基本都是深度学习了&#xff0c;但是传统的机器学习也能做。本案…

Lunaproxy与711Proxy的对比与优劣分析

今天我们来深入对比两款在市场上备受关注的代理IP服务&#xff1a;Lunaproxy和711Proxy。接下来&#xff0c;我们将从多个角度对这两款服务进行详细分析&#xff0c;帮助大家做出明智的选择。 优势分析 711Proxy的优势 1. 性价比高&#xff1a;711Proxy提供多种灵活的套餐选…

【电商干货分享】干货速看!电商数据集大全!

数据分析——深入探索中小企业数字化转型&#xff0c;专注提供各行业数据分析干货、分析技巧、工具推荐以及各类超实用分析模板&#xff0c;为钻研于数据分析的朋友们加油充电。 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff0…

C# Application.DoEvents()的作用

文章目录 1、详解 Application.DoEvents()2、示例处理用户事件响应系统事件控制台输出游戏和多媒体应用与操作系统的交互 3、注意事项总结 Application.DoEvents() 是 .NET 框架中的一个方法&#xff0c;它主要用于处理消息队列中的事件。在 Windows 应用程序中&#xff0c;当一…

芯片基识 | 掰开揉碎讲 FIFO(同步FIFO和异步FIFO)

文章目录 一、什么是FIFO二、为什么要用FIFO三、什么时候用FIFO四、FIFO分类五、同步FIFO1. 同步FIFO电路框图2. 同步FIFO空满判断3. 同步FIFO设计代码4. 同步FIFO仿真结果 六、异步FIFO1、异步FIFO的电路框图2 、亚稳态3、打两拍4、格雷码5、如何判断异步FIFO的空满&#xff0…

3D Web轻量化平台HOOPS Web Platform的功能与应用分析

随着3D技术在多个行业的广泛应用&#xff0c;对于3D模型轻量化的需求日益增长。HOOPS Web Platform作为一个先进的3D模型轻量化平台&#xff0c;为开发人员提供了一整套工具来构建和部署基于Web的工程应用程序。本文将分析HOOPS Web Platform的核心功能和它在不同领域的应用情况…

VBA初学:零件成本统计之一(任务汇总)

经过前期一年多对金蝶K3生产任务流程和操作的改造和优化&#xff0c;现在总算可以将零件加工各个环节的成本进行归集了。 原本想写存储过程&#xff0c;通过直接SQL报表做到K3中去的&#xff0c;但财务原本就是用EXCEL&#xff0c;可以方便调整和保存&#xff0c;加上还有一部分…

破解在制品管理不透明难题

在快节奏的现代工业浪潮中&#xff0c;每一个细微的管理环节都直接关系到企业的竞争力与盈利能力。在车间生产中&#xff0c;在制品管理流程不透明是一个常见问题&#xff0c;它可能导致生产效率低下、成本增加、库存积压以及沟通障碍等负面影响。 在制品管理流程不透明&#x…

ETAS工具导入Com Arxml修改步骤

文章目录 前言Confgen之前的更改Confgen之后的修改CANCanIfComComMEcuM修改CanNmCanSMDCMCanTp生成RTE过程报错修改DEXT-诊断文件修改Extract问题总结前言 通讯协议栈开发一般通过导入DBC实现,ETAS工具本身导入DBC也是生成arxml后执行cfggen,本文介绍直接导入客户提供的arxml…

8种数据迁移工具

前言 最近有些小伙伴问我&#xff0c;ETL数据迁移工具该用哪些。 ETL(是Extract-Transform-Load的缩写&#xff0c;即数据抽取、转换、装载的过程)&#xff0c;对于企业应用来说&#xff0c;我们经常会遇到各种数据的处理、转换、迁移的场景。 今天特地给大家汇总了一些目前…

迭代加深——AcWing 170. 加成序列

迭代加深 定义 迭代加深搜索&#xff08;Iterative Deepening Depth-First Search, IDS&#xff09;是一种结合了深度优先搜索&#xff08;DFS&#xff09;和广度优先搜索&#xff08;BFS&#xff09;特点的算法。它通过限制搜索树的深度来控制搜索范围&#xff0c;起初以较小…

CTFShow的RE题(一)

RE2 1.中文字符的显示 2.对文件的读取操作 3.RC4加密 &#xff08;有一点是魔改的&#xff09; 4.enflag.txt文件里面的密文是ASCII编码之后的数据(可以放ida中) 也可以放到 010 里&#xff08;推荐&#xff09; encDH~mqqvqxB^||zllJq~jkwpmvez{ key for i in enc:keychr…

程序员下班为什么不关电脑?难道在偷偷加班?!

不管是周围的程序员朋友还是网上的很多程序员朋友&#xff0c;在下班后都是习惯不关电脑的&#xff0c;关上显示器&#xff0c;拿上手机&#xff0c;快乐下班&#xff01; 那么&#xff0c;为什么程序员下班都不关电脑&#xff1f;难道他们在偷偷加班&#xff1f; 其实&#x…

elasticsearch源码分析-04集群状态发布

集群状态发布 cluster模块封装了在集群层面执行的任务&#xff0c;如集群健康、集群级元信息管理、分片分配给节点、节点管理等。集群任务执行之后可能会产生新的集群状态&#xff0c;如果产生新的集群状态主节点会将集群状态广播给其他节点。 集群状态封装在clusterState中&…

基于Qt实现的PDF阅读、编辑工具

记录一下实现pdf工具功能 语言&#xff1a;c、qt IDE&#xff1a;vs2017 环境&#xff1a;win10 一、功能演示&#xff1a; 二、功能介绍&#xff1a; 1.基于saribbon主体界面框架&#xff0c;该框架主要是为了实现类似word导航项 2.加载PDF放大缩小以及预览功能 3.pdf页面跳转…