PageHelper分页

  1. 1. SpringBoot集成MySQL - MyBatis PageHelper分页
    1. 1.0.1. PageHelper是如何实现物理分页的前提:MyBatis的插件机制?
  2. 1.1. 测试案例:
    1. 1.1.1. 后台代码:
    2. 1.1.2. 前台代码:
    3. 1.1.3. 测试结果:
    4. 1.1.4. 总结:
  • 2. 使用PageHelper有何注意点

  • SpringBoot集成MySQL - MyBatis PageHelper分页

    为什么会出现PageHelper这类框架?

    这便要从逻辑分页和物理分页开始说起:

    • 逻辑分页:从数据库中将所有记录查询出来,存储到内存中,展示当前页,然后数据再直接从内存中获取(前台分页)
    • 物理分页:只从数据库中查询当前页的数据(后台分页)

    由于MyBatis默认实现中采用的是逻辑分页,所以才诞生了PageHelper一类的物理分页框架。

    PageHelper是如何实现物理分页的前提:MyBatis的插件机制?

    • MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。那么拦截器拦截MyBatis中的哪些内容呢?

    • Mybatis的分页功能很弱,它是基于内存的分页(查出所有记录再按偏移量和limit取结果),在大数据量的情况下这样的分页基本上是没有用的。

    测试案例:

    1
    2
    3
    4
    5
    <!--添加分页插件-->
    <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    </dependency>

    配置文件:

    1
    2
    3
    4
    5
    6
    # 分页配置
    pagehelper:
    helper-dialect: mysql
    reasonable: true
    support-methods-arguments: true
    params: count=countSql

    当请求页数小于第一页时,显示第一页数据;

    显示的页数大于最后一页(显示最后一页数据)

    后台代码:

    ProductController.java

    1
    2
    3
    4
    5
    6
    7
    8
    @GetMapping("/list")
    public Result<Shop> getList(int pageNum, int pageSize) {
    // 调用业务逻辑,返回数据
    List<Shop> list = productService.lists(pageNum, pageSize);
    //获取总条数, 否则前端下一页按钮用不了
    Long total = ((Page)list).getTotal();
    return Result.success(list, total);
    }

    ProductServiceImpl.java

    1
    2
    3
    4
    5
    6
    7
    @Override
    public List<Shop> lists(int pageNum, int pageSize) {
    //使用分页插件,核心代码就这一行
    PageHelper.startPage(pageNum, pageSize);
    // 获取
    return productDao.lists();
    }

    ProductDao.java 接口

    1
    2
    @Select("select * from shop")
    List<Shop> lists();

    Result.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    public class Result<T> {
    /** 状态码 */
    private Integer code;

    /** 提示信息 */
    private String msg;

    /** 响应数据 */
    private T data;

    private long total;


    public static Result success(Object data, long total) {
    return new Result(200, "success", data, total);
    }

    public static Result successNoData(String msg) {
    return new Result(200, msg, null, 0);
    }

    public static Result error( String msg) {
    return new Result(505, msg,null,0);
    }
    }

    请求url: http://localhost:8081/list?pageNum=1&pageSize=4

    即可返回数据。

    前台代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    <template>
    <div>
    <el-table :data="state.tableData.data" height="350" style="width: 100%">
    <el-table-column prop="shopId" label="id" width="180" />
    <el-table-column prop="shopName" label="商品名称" width="180" />
    <el-table-column prop="shopExplain" label="商品简介" width="180" />
    <el-table-column prop="shopPrice" label="商品价格" width="180" />

    <el-table-column prop="shopImg" label="商品图片">
    <template #default="scope">
    <el-image
    style="width: 70px; height: 70px"
    :src="scope.row.shopImg"
    ></el-image>
    </template>
    </el-table-column>
    </el-table>

    <!-- <el-pagination
    :current-page="pageHelper.queryInfo.pageNum"
    :page-sizes="[5, 10, 15, 20]"
    :page-size="pageHelper.queryInfo.pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="state.tableData.length"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    > </el-pagination>-->
    </div>
    <div>
    <el-pagination
    background
    layout="prev, pager, next"
    :total="state.tableData.total"
    :current-page="pageHelper.queryInfo.pageNum"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    />
    </div>
    </template>

    <script setup>
    import axios from "axios";
    import { reactive } from "vue";

    const state = reactive({
    tableData: [],
    });

    const url = `/api/list`;

    const pageHelper = reactive({
    queryInfo: {
    query: "", // 查询参数
    pageNum: 1, // 当前页码
    pageSize: 5, // 每页显示条数
    },
    });

    function init_date() {
    axios
    .get(url, { params: pageHelper.queryInfo })
    .then((result) => {
    state.tableData = result.data;
    console.log(state.tableData);
    console.log(state.tableData.total);
    })
    .catch((err) => {
    console.log(err);
    });
    }
    init_date();

    // 监听 page size 改变的事件
    function handleSizeChange(newSize) {
    pageHelper.queryInfo.pageSize = newSize;
    init_date();
    }
    // 监听 页码值 改变的事件
    function handleCurrentChange(newPage) {
    pageHelper.queryInfo.pageNum = newPage;
    init_date();
    }
    </script>

    <style scoped></style>

    测试结果:

    加了图片上去:

    总结:

    后台:

    1. 使用PageHelper分页,pageInfo.getTotal()返回的是当前页数据而不是总数的问题。

      解决办法:将返回的list强转成Page,然后getTotal()即可

    一定要指定所有数据的总数,而不是需要查询的部分数据的总数! 否则下一页按钮将用不了!

    参考:https://blog.csdn.net/qq_28988969/article/details/78082116?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-78082116-blog-113795004.pc_relevant_aa_2&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-78082116-blog-113795004.pc_relevant_aa_2&utm_relevant_index=1

    使用PageHelper有何注意点

    ​ 只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会被分页。

    ​ 请不要配置多个分页插件:请不要在系统中配置多个分页插件(使用Spring时,mybatis-config.xmlSpring<bean>配置方式,请选择其中一种,不要同时配置多个分页插件)!