Mybatis/Plus 分页查询

 

分页查询的原理是通过将大数据量集分割成较小的部分来返回结果,以减少一次性加载和显示的数量。

接受分页参数:在分页查询中,通常会接收两个关键的参数——当前页码(current)和每页显示的数据量(size)。这些参数决定了用户希望查看哪一部分数据。

计算偏移量:根据当前页码和每页显示数据量,计算出从数据库中哪一行数据开始获取。偏移量公式:

      start = (current - 1)* size; start 的值就是数据集中的起始位置。

执行分页查询:在SQL查询中使用 Limit 字句来限制查询返回的记录数。Limit 接受两个参数——偏移量 start 和 每页显示的记录数 size,指示数据库从偏移量处开始,返回指定数量的记录。如:

select * from table_name limit start, size;
-- 这条语句将从 start 位置开始获取,获取 size 条记录。

   还有 像 PageHelper 或 RowBounds 这样的分页工具,分页查询原理虽然与 Limit 查询类似,但过程更加简化和自动化。通过简化分页原理,自动处理分页参数并返回分页后的数据。

构建查询条件:分页查询中,通常还会结合其他条件(如筛选条件),来进一步缩小查询范围。条件可以通过 where 子句进行过滤,以满足查询要求。

返回结果:数据库执行查询后,将结果集返回给应用程序。程序将结果进行展示,用户使用时可以通过调整页码和每页记录数,查看不同的部分。

通过分页查询,系统可以有效减少内存占用和网络传输的压力,提升响应速度,特别是在数据量非常大的情况下。

 

1. 在SQL内分页

SQL 使用 Limit。可以直接单表使用,也可以多表实现。

只返回数据,不返回查询总数。    

分页查询类:

/**
 * 分页
 */
@Data
public class PageShowDto {

    /** 初始页 */
    private Integer current;
    /** 数量 */
    private Integer size;
    /** 开始 */
    private Integer start;

}

 

Service实现类:

    /**
     * 查询
     *
     * @param pageDto  分页
     * @param steamDto 条件
     * @return 信息
     */
    @Override
    public List<ExerciseSchemeSteamDto> findExerciseType(ExerciseSchemeSteamDto steamDto, PageShowDto pageDto) {

        pageDto.setStart((pageDto.getCurrent() - 1) * pageDto.getSize());

        return exerciseSchemeAndSteamMapper.findExerciseSchemeSteamType(steamDto, pageDto);

    }
current--起始页;
size--每页条数;
pageDto.getCurrent() - 1) * pageDto.getSize()-- 如:(current 3 - 1) * size 10 为 20;此时 start 为 20;

Mappe接口:

    /** 查询 */
    List<ExerciseSchemeSteamDto> findExerciseSchemeSteamType(@Param("steamDto") ExerciseSchemeSteamDto steamDto, @Param("pageDto") PageShowDto pageDto);

 

XML编写SQL:

    <!-- 查询两个表   -->    
    <select id="findExerciseSchemeSteamType"
            resultType="com.control.interactive.entity.dto.ExerciseSchemeSteamDto">
        select
        es.id,
        es.stage_name as stageName,
        es.condition_scenario as conditionScenario,
        es.red_team_action as redTeamAction,
        ess.team_id as teamId,
        ess.team_name as teamName,
        ess.action_command as actionCommand,
        ess.scheme_id as schemeId
        from t_exercise_scheme es
            left join t_exercise_scheme_team ess
        on es.id = ess.scheme_id
        <where>
            <if test="steamDto.stageName != null and steamDto.stageName != ''">
                es.stage_name like concat('%', #{steamDto.stageName}, '%')
            </if>
        </where>
        order by es.id
        <if test="pageDto != null">
            limit #{pageDto.size} offset #{pageDto.start}
        </if>
    </select>
current--起始页;
size--每页条数;
pageDto.getCurrent() - 1) * pageDto.getSize()-- 如:(current 3 - 1) * size 10 为 20;此时 start 为 20;
此时分页查询是从 第21条 数据开始截取,每页 10条 数据。

 

查询直接传递参数 current 与 size。想进一步使用条件过滤,直接传递相应的字段,如 name-模糊查询等等...

 

优化返回结果,可以使用 `com.baomidou.mybatisplus.extension.plugins.pagination.Page` 的 Page<> 返回。

 

2. 使用 PageHelper 插件

PageHelper 是 Mybatis 中常用的分页插件。再查询SQL前,自动处理分页逻辑并为查询语句添加适当的 Limit 字句。

 

注入依赖:

        <!-- PageHelper 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>

PS:注入依赖使用 注意 与 JSqlParser 的版本冲突,根据情况进行升降 pagehelper 版本。

 

自定义分页查询类,用于前端传值:

/**
 * 分页
 */
@Data
public class PageShowDto {

    /** 初始页 */
    private Integer current;
    /** 数量 */
    private Integer size;

}

 

ServiceImpl:

初始化分页:在调用查询方法前,通过 PageHelper.startPage(current, size) 设置当前页码和每页显示的记录数。

 ~~ PageHelper.startPage(1, 10);

    /**
     * 查询
     *
     * @param pageDto 分页
     * @param steamDto        条件
     * @return 信息
     */
    @Override
    public R<PageInfo<ExerciseSchemeSteamDto>> findExercise(PageShowDto pageDto, ExerciseSchemeSteamDto steamDto) {

        // 分页参数设置
        PageHelper.startPage(pageDto.getPageNum(), pageDto.getPageSize());
        List<ExerciseSchemeSteamDto> exerciseSchemeSteam = exerciseSchemeAndSteamMapper.findExerciseSchemeSteam(steamDto);

        PageInfo<ExerciseSchemeSteamDto> steamPageInfo = new PageInfo<>(exerciseSchemeSteam);
        return R.ok(steamPageInfo);
    }

PageHelper 拦截SQL语句,再执行SQL前自动添加 Limit 和 Offset 子句,便于在数据库表中查询所需数据。

 

XML SQL 编写:

    /** 查询 */
    List<ExerciseSchemeSteamDto> findExerciseSchemeSteam(@Param("steamDto") ExerciseSchemeSteamDto steamDto);

 

    <!-- 查询-->
    <select id="findExerciseSchemeSteam"
            resultType="com.hrzn.control.interactive.blue.entity.dto.ExerciseSchemeSteamDto">
        select
        es.id as id,
        es.stage_name as stageName,
        es.condition_scenario as conditionScenario,
        es.red_team_action as redTeamAction,
        ess.team_id as teamId,
        ess.team_name as teamName,
        ess.action_command as actionCommand,
        ess.scheme_id as schemeId
        from t_exercise_scheme es left join t_exercise_scheme_team ess
        on es.id = ess.scheme_id
        <where>
            <if test="steamDto.stageName != null and steamDto.stageName != ''">
                es.stage_name like concat('%', #{steamDto.stageName}, '%')
            </if>
        </where>
        order by es.id;
    </select>

后台会通过 PageHelper 将SQL 改为 select (字段) from (表名) limit 0, 10;

 

返回结果:查询完成后,优化查询返回结果可以使用 PageInfo<>,PageHelper 会将结果封装到一个 PageInfo对象,其中包含查询结果、总数据量、总页数等分页信息。

 

优点:

  简化分页代码:只需要调用 startPage() 方法,分页逻辑自动处理。

  集成度高:与 Mybatis 无缝集成,直接应用于现有的 Mybatis 查询。

 

简单使用https://www.cnblogs.com/warmNest-llb/p/18120512

 

3. 使用 RowBounds 分页

RowBounds 是 Mybatis 自带的一种分页处理方式,通过逻辑分页(在内存中分页)来控制查询结果的范围。

 

RowBounds:

 

构建查询:

    /**
     * 查询
     *
     * @param schemeSteamPage 条件
     * @param pageDto 分页
     * @return true
     */
    @Override
    public List<ExerciseSchemeSteamDto> findExerciseRowBounds(ExerciseSchemeSteamDto schemeSteamPage, PageShowDto pageDto) {
        RowBounds rowBounds = new RowBounds((pageDto.getCurrent() - 1) * pageDto.getSize(), pageDto.getSize());
        return exerciseSchemeAndSteamMapper.findExerciseSchemeSteamRow(schemeSteamPage, rowBounds);
    }

构建 RowBounds 对象:通过 创建一个 RowBounds 对象,传入偏移量 offsert 和 每页记录数 limit;

new RowBounds((pageDto.getCurrent() - 1) * pageDto.getSize(), pageDto.getSize()) 等价于 new RowBounds(offset, size);

 offset 从哪行数据开始,size 多少条数据。

 

XML 编写 SQL:

    /** 查询 */
    List<ExerciseSchemeSteamDto> findExerciseSchemeSteamRow(@Param("steamDto") ExerciseSchemeSteamDto steamDto, RowBounds rowBounds);

 

    <!-- 演练查询-->
    <select id="findExerciseSchemeSteam"
            resultType="com.hrzn.control.interactive.blue.entity.dto.ExerciseSchemeSteamDto">
        select
        es.id as id,
        es.stage_name as stageName,
        es.condition_scenario as conditionScenario,
        es.red_team_action as redTeamAction,
        ess.team_id as teamId,
        ess.team_name as teamName,
        ess.action_command as actionCommand,
        ess.scheme_id as schemeId
        from t_exercise_scheme es left join t_exercise_scheme_team ess
        on es.id = ess.scheme_id
        <where>
            <if test="steamDto.stageName != null and steamDto.stageName != ''">
                es.stage_name like concat('%', #{steamDto.stageName}, '%')
            </if>
        </where>
        order by es.id;
    </select>

 

 

查询与分页:Mybatis 执行查询时,将结果集取回后,根据 RowBounds 进行内存级别的分页处理。这种方式下分页逻辑是在应用程序内存中执行的,而不是在SQL查询中添加 Limit 子句。

 

 

优点:

  无需改动原始SQL:可以直接作用于已有的 Mybatis 查询。

 

缺点:

  适合小数据集:由于是内存中处理分页逻辑,对于大数据集来说性能较差。通常不推荐在大数据集上使用 RowBounds 进行分页。

 

 

4. 总结

 直接在SQL内分页,简单粗暴。

 PageHelper 自动化处理分页查询,拦截并改写 SQL,性能高,适合大数据集,推荐在 Mybatis 中使用。

 RowBounds 则是基于内存的分页方式,简单直接,但对于大数据集性能不佳,通常只适合处理小数据集的分页。

 

 


 

posted @ 2024-09-04 14:26  学Java的`Bei  阅读(3523)  评论(0编辑  收藏  举报