MyBatis-Plus模块扩展分页查询

1.说明

  1. 对MyBatisPlus的分页插件进行扩展,并且实现一行调用分页
  2. 对EasyCode模板进行升级

2.common-mybatis-plus-starter

1.目录结构

CleanShot 2025-01-26 at 13.41.08@2x

2.MybatisPLusAutoConfiguration.java 添加MyBatis Plus分页插件
/**
 * 添加MyBatis Plus分页插件
 */
@Bean
@ConditionalOnMissingBean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    log.info("MybatisPlusInterceptor.PaginationInnerInterceptor 注入成功!");
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 如果配置多个插件, 切记分页最后添加
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
    return interceptor;
}
3.PlusPageResult.java MyBatis Plus 分页对象的增强版
package cn.sunxiansheng.mybatis.plus.page.plus;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import lombok.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * PlusPageResult 是 MyBatis Plus 分页对象的增强版。
 * <p>
 * 此类扩展了分页功能,兼容 MyBatis Plus 的 {@link IPage} 接口,并添加了额外的元数据字段,
 * 如总页数、起始和结束位置、是否有上一页/下一页等。
 * </p>
 *
 * @param <T> 分页中记录的类型
 * @Author sun
 * @Create 2025/1/26 09:57
 * @Version 2.0
 */
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class PlusPageResult<T> implements IPage<T> {

    private static final long serialVersionUID = 1L;

    /**
     * 当前页码,从 1 开始
     */
    private long current = 1;

    /**
     * 每页显示的记录数
     */
    private long size = 10;

    /**
     * 总记录条数
     */
    private long total = 0;

    /**
     * 当前页的记录列表
     */
    private List<T> records = new ArrayList<>();

    /**
     * 排序信息列表
     */
    private List<OrderItem> orders = new ArrayList<>();

    /**
     * 当前页的起始记录位置
     */
    private long start;

    /**
     * 当前页的结束记录位置
     */
    private long end;

    /**
     * 总页数
     */
    private long totalPages;

    /**
     * 是否有下一页
     */
    private boolean hasNextPage;

    /**
     * 是否有上一页
     */
    private boolean hasPreviousPage;

    /**
     * 自定义构造器。
     *
     * @param current 当前页码
     * @param size    每页显示的记录数
     * @param total   总记录条数
     * @param records 当前页的记录列表
     */
    public PlusPageResult(long current, long size, long total, List<T> records) {
        this.current = current;
        this.size = size;
        this.total = total;
        this.records = records != null ? records : Collections.emptyList();
        calculateMetaData();
    }

    // ========== IPage 接口方法实现 ==========

    /**
     * 获取当前页的记录列表。
     *
     * @return 当前页的记录列表
     */
    @Override
    public List<T> getRecords() {
        return records;
    }

    /**
     * 设置当前页的记录列表。
     *
     * @param records 当前页的记录列表
     * @return 当前分页对象
     */
    @Override
    public IPage<T> setRecords(List<T> records) {
        this.records = records;
        return this;
    }

    /**
     * 获取总记录条数。
     *
     * @return 总记录条数
     */
    @Override
    public long getTotal() {
        return total;
    }

    /**
     * 设置总记录条数。
     *
     * @param total 总记录条数
     * @return 当前分页对象
     */
    @Override
    public IPage<T> setTotal(long total) {
        this.total = total;
        calculateMetaData();
        return this;
    }

    /**
     * 获取每页显示的记录数。
     *
     * @return 每页显示的记录数
     */
    @Override
    public long getSize() {
        return size;
    }

    /**
     * 设置每页显示的记录数。
     *
     * @param size 每页显示的记录数
     * @return 当前分页对象
     */
    @Override
    public IPage<T> setSize(long size) {
        this.size = size;
        calculateMetaData();
        return this;
    }

    /**
     * 获取当前页码。
     *
     * @return 当前页码
     */
    @Override
    public long getCurrent() {
        return current;
    }

    /**
     * 设置当前页码。
     *
     * @param current 当前页码
     * @return 当前分页对象
     */
    @Override
    public IPage<T> setCurrent(long current) {
        this.current = current;
        calculateMetaData();
        return this;
    }

    /**
     * 获取排序信息列表。
     *
     * @return 排序信息列表
     */
    @Override
    public List<OrderItem> orders() {
        return orders;
    }

    // ========== 功能扩展 ==========

    /**
     * 计算分页的元数据信息,包括总页数、起始/结束位置,以及是否有上一页和下一页。
     */
    private void calculateMetaData() {
        // 计算总页数
        if (size > 0) {
            this.totalPages = (total / size) + (total % size == 0 ? 0 : 1);
        } else {
            this.totalPages = 0;
        }

        // 计算起始和结束位置
        if (size > 0) {
            this.start = (current - 1) * size + 1;
            this.end = Math.min(current * size, total);
        } else {
            this.start = 1;
            this.end = total;
        }

        // 是否有上一页和下一页
        this.hasPreviousPage = current > 1;
        this.hasNextPage = current < totalPages;
    }
}
4.SunPlusPageHelper.java 分页工具类
package cn.sunxiansheng.mybatis.plus.page.plus;

import java.util.function.Function;

/**
 * SunPlusPageHelper 是一个 MyBatis Plus 分页工具类。
 * <p>
 * 提供静态方法简化分页查询的逻辑,用户可以通过提供查询逻辑的函数来完成分页数据的获取。
 * </p>
 *
 * @Author sun
 * @Create 2025/1/26 12:11
 * @Version 1.0
 */
public class SunPlusPageHelper {

    /**
     * 执行分页查询。
     * <p>
     * 此方法通过创建一个 {@link PlusPageResult} 分页对象并传递给查询函数,返回查询结果。
     * </p>
     *
     * @param current  当前页码,从 1 开始
     * @param pageSize 每页显示的记录数
     * @param clazz    分页对象中的记录类型的 {@link Class} 类型
     * @param function 分页查询的函数,接收 {@link PlusPageResult} 参数并返回查询结果
     * @param <T>      分页记录的类型
     * @return 包含分页结果的 {@link PlusPageResult} 对象
     */
    public static <T> PlusPageResult<T> paginate(long current, long pageSize, Class<T> clazz, Function<PlusPageResult<T>, PlusPageResult<T>> function) {
        // 创建分页对象
        PlusPageResult<T> pageResult = (PlusPageResult<T>) new PlusPageResult<T>().setCurrent(current).setSize(pageSize);
        // 使用分页对象作为参数进行分页查询并返回查询结果
        return function.apply(pageResult);
    }
}

3.EasyCode模板修改

CleanShot 2025-01-26 at 14.52.33@2x

4.common-mybatis-plus-starter-demo 分页代码说明

1.ExampleTableController.java
/**
 * 分页查询数据。
 *
 * @param exampleTableReq 分页查询请求对象
 * @return 分页查询结果封装
 */
@GetMapping("/queryPage")
public PlusPageResult<ExampleTableVo> queryPage(@RequestBody ExampleTableReq exampleTableReq) {
    // ============================== 参数校验 ==============================
    // 可以添加必要的参数校验逻辑

    // ============================== 调用Service层 ==============================
    return exampleTableService.queryPage(exampleTableReq);
}
2.ExampleTableService.java
package cn.sunxiansheng.mybatis.plus.service;

import cn.sunxiansheng.mybatis.plus.base.service.SunRaysBaseService;
import cn.sunxiansheng.mybatis.plus.entity.po.ExampleTable;
import cn.sunxiansheng.mybatis.plus.entity.req.ExampleTableReq;
import cn.sunxiansheng.mybatis.plus.entity.vo.ExampleTableVo;
import cn.sunxiansheng.mybatis.plus.page.plus.PlusPageResult;

/**
 * 示例表(ExampleTable)Service接口:定义业务逻辑
 *
 * @author sun
 * @since 2025-01-26 14:33:02
 */
public interface ExampleTableService extends SunRaysBaseService<ExampleTable, java.lang.Integer> {

    /**
     * 使用MyBatis Plus 的分页插件进行分页查询
     *
     * @param exampleTableReq 请求参数,需要携带pageNo和pageSize
     * @return 返回vo的PlusPageResult
     */
    PlusPageResult<ExampleTableVo> queryPage(ExampleTableReq exampleTableReq);
}
3.ExampleTableServiceImpl.java
@Override
@Transactional(rollbackFor = Exception.class) // 开启事务
public PlusPageResult<ExampleTableVo> queryPage(ExampleTableReq exampleTableReq) {
    // 将req转换为po
    ExampleTable po = ExampleTableConverter.INSTANCE.convertReq2Po(exampleTableReq);

    // 分页查询
    PlusPageResult<ExampleTable> poPageResult = SunPlusPageHelper.paginate(
            exampleTableReq.getPageNo(),
            exampleTableReq.getPageSize(),
            ExampleTable.class,
            (plusPageResult) -> {
                // 这里会给出已经封装好的page对象,开发者必须携带!后面的参数就是查询的条件,可自定义
                return exampleTableMapper.queryPage(plusPageResult, po);
            });

    // 将po转换为vo并返回
    return ExampleTableConverter.INSTANCE.convertPoPage2VoPage(poPageResult);
}
4.ExampleTableMapper.java
/**
 * MyBatisPlus 分页插件的分页查询
 *
 * @param plusPageResult
 * @param po
 * @return
 */
PlusPageResult<ExampleTable> queryPage(@Param("plusPageResult") PlusPageResult<ExampleTable> plusPageResult, @Param("po") ExampleTable po);
5.ExampleTableMapper.xml
<!-- MyBatisPlus 分页插件的分页查询 -->
<select id="queryPage" resultMap="ExampleTableMap">
    select id, user_name, user_email, phone_number, home_address, account_status, create_by, create_time, update_by,
    update_time, is_deleted
    from example_table
    <where>
        <if test="po.id != null">
            and id = #{po.id}
        </if>
        <if test="po.userName != null and po.userName != ''">
            and user_name = #{po.userName}
        </if>
        <if test="po.userEmail != null and po.userEmail != ''">
            and user_email = #{po.userEmail}
        </if>
        <if test="po.phoneNumber != null and po.phoneNumber != ''">
            and phone_number = #{po.phoneNumber}
        </if>
        <if test="po.homeAddress != null and po.homeAddress != ''">
            and home_address = #{po.homeAddress}
        </if>
        <if test="po.accountStatus != null">
            and account_status = #{po.accountStatus}
        </if>
        <if test="po.createBy != null and po.createBy != ''">
            and create_by = #{po.createBy}
        </if>
        <if test="po.createTime != null">
            and create_time = #{po.createTime}
        </if>
        <if test="po.updateBy != null and po.updateBy != ''">
            and update_by = #{po.updateBy}
        </if>
        <if test="po.updateTime != null">
            and update_time = #{po.updateTime}
        </if>
        <if test="po.isDeleted != null">
            and is_deleted = #{po.isDeleted}
        </if>
        and is_deleted = 0
    </where>
</select>
MyBatis-Plus是一个基于MyBatis的增强工具,提供了许多便捷的功能来简化开发。其中,MyBatis-Plus-join是MyBatis-Plus的一个扩展模块,用于支持关联查询。 在使用MyBatis-join的依赖。可以在项目的pom.xml文件中添加如下依赖: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>3.4.3.1</version> </dependency> ``` 2. 在实体类中定义关联关系。使用MyBatis-Plus-join时,需要在实体类中定义关联关系,可以使用`@TableField`注解来指定关联字段。例如: ```java public class User { private Long id; private String name; @TableField(exist = false) private List<Role> roles; // getter and setter } public class Role { private Long id; private String roleName; // getter and setter } ``` 3. 编写Mapper接口。在Mapper接口中,可以使用`@Select`注解来编写关联查询的SQL语句。例如: ```java @Mapper public interface UserMapper extends BaseMapper<User> { @Select("SELECT u.*, r.* FROM user u LEFT JOIN user_role ur ON u.id = ur.user_id LEFT JOIN role r ON ur.role_id = r.id") @Results({ @Result(property = "id", column = "id"), @Result(property = "name", column = "name"), @Result(property = "roles", column = "id", many = @Many(select = "com.example.mapper.RoleMapper.selectByUserId")) }) List<User> selectUserWithRoles(Page<User> page); } ``` 4. 编写关联查询的子查询。在上面的例子中,使用了`@Many`注解来指定关联查询的子查询方法。例如: ```java @Mapper public interface RoleMapper extends BaseMapper<Role> { @Select("SELECT r.* FROM role r LEFT JOIN user_role ur ON r.id = ur.role_id WHERE ur.user_id = #{userId}") List<Role> selectByUserId(Long userId); } ``` 5. 调用分页查询方法。在Service层或者Controller层中,可以调用Mapper接口中定义的分页查询方法来进行查询。例如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public IPage<User> getUserWithRoles(Page<User> page) { return userMapper.selectUserWithRoles(page); } } ``` 以上就是使用MyBatis-Plus-join进行分页查询的基本步骤。通过定义关联关系和编写关联查询的SQL语句,可以方便地进行关联查询并实现分页功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

S-X-S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值