MyBatis 分页拦截器实现总结

1. 目的

由于若依自带的分页偶尔会失效,因为他那个是mybatisplus,但是我都是自己手写的xml和sql
所以为了实现手写sql的自动分页,实现一个 MyBatis 拦截器,用于自动处理手写 SQL 查询的分页功能。

2. 拦截器实现

2.1 创建拦截器类

创建一个名为 PaginationInterceptor 的类,继承自 Interceptor 接口。

package com.ruoyi.common.interceptor;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * 拦截手写xml,实现手写sql的自动分页
 */
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {String.class, Object.class, RowBounds.class, org.apache.ibatis.session.ResultHandler.class})
})
public class PaginationInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取分页参数
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();

        // 检查 pageNum 和 pageSize 是否有效
        if (pageNum != null && pageSize != null && pageNum > 0 && pageSize > 0) {
            // 开始分页
            PageHelper.startPage(pageNum, pageSize);
        }

        // 执行原始查询
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以在这里设置拦截器的属性
    }
}

2.2 注册拦截器

application.yml 中注册拦截器:

mybatis:
  configuration:
    plugins:
      - com.ruoyi.common.interceptor.PaginationInterceptor

3. Mapper 方法

确保 Mapper 方法的签名与拦截器的 @Signature 注解中的参数匹配。示例:

@Mapper
public interface OrderMapper {
    List<Order> selectOrderList(Order order);
}

4. 使用分页工具

在调用 Mapper 方法时,使用 PageUtils.startPage() 来启动分页:

public List<Order> getOrders(Order order) {
    PageUtils.startPage(); // 自动获取分页参数
    return orderMapper.selectOrderList(order); // 调用手写 SQL 查询
}

5. 测试和验证

  • 检查 SQL 日志:确保生成的 SQL 查询中包含 LIMITOFFSET
  • 验证结果:确保返回的结果符合预期的分页数据。

6. 常见问题排查

  • 确保拦截器已正确注册。
  • 检查 Mapper 方法的签名是否匹配。
  • 确保没有其他拦截器冲突。
  • 调试拦截器,确认其是否被调用。

7. 结论

通过实现 PaginationInterceptor,可以为手写 SQL 查询提供自动分页支持,提高代码的灵活性和可维护性。