生产中常用的拦截器 实现mybatis分页插件

注:mapper中的方法必须以ByPage结尾,例:selectByPage();

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;
//@Signature:是对插件需要拦截的对象进行签名,type:表示要拦截的类型,method表示拦截类中的方法,args:是需要的参数,
//这里的参数在后面也可以获取到.statementHandler:数据库会话器专门用于处理数据库会话:statement的执行操作,是一个接口
@Component
@Intercepts(@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class}
))
public class PagePlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        /**
         * 1.拿到原始sql
         * 2.修改原始sql,增加分页 select * from user limit 0,10
         * 3.执行jdbc去查询总数
         */
        //从invocation中拿到StatementHandler对象
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();

        //拿到原始sql
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        System.out.println("原始sql为:"+sql);

        //分页参数
        Object parameterObject = boundSql.getParameterObject();
        //statementHandler 转换成metaObject
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");

        //获取mapper接口中的方法名称 selectByPage
        String mapperMethodName = mappedStatement.getId();
        if(mapperMethodName.matches(".*ByPage$")){
            Map<String,Object> params = (Map<String,Object>)parameterObject;
            PageInfo pageInfo = (PageInfo) params.get("page");//map.put("page",pageInfo);
            String countSql = "select count(0) from ("+sql+") a";
            System.out.println("查询总数的sql:"+countSql);

            //执行jdbc操作
            Connection connection = (Connection) invocation.getArgs()[0];
            PreparedStatement countStatement = connection.prepareStatement(countSql);
            ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
            parameterHandler.setParameters(countStatement);
            ResultSet resultSet = countStatement.executeQuery();
            if(resultSet.next()){
                pageInfo.setTotalNumber(resultSet.getInt(1));
            }
            resultSet.close();
            countStatement.clearParameters();
            String pageSql = generaterPageSql(sql,pageInfo);
            System.out.println("分页sql为:"+pageSql);
            metaObject.setValue("delegate.boundSql.sql",pageSql);
        }

        //将执行流程交给mybatis继续去执行
        return invocation.proceed();
    }

    //根据原始sql生成limit分页sql
    public String generaterPageSql(String sql,PageInfo pageInfo){
        StringBuffer sb = new StringBuffer();
        sb.append(sql);
        sb.append(" limit "+pageInfo.getStartIndex()+" , "+pageInfo.getTotalSelect());
        return sb.toString();
    }
    /**
     * 将自定义的插件放入到mybatis中去执行
     * @param o
     * @return
     */
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
public class PageInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    private int totalNumber;//当前表中总条目数
    private int currentPage;//当前页的位置
    private int totalPage;//总页数
    private int pageSize = 3;//每页条目数
    private int startIndex;//检索的起始位置
    private int totalSelect;//检索的总条目数
 
    //其他get set方法去掉了
    public void setTotalNumber(int totalNumber) {
        this.totalNumber = totalNumber;
        this.count();
    }
    //计算
    private void count() {
        int totalPageTemp = this.totalNumber/this.pageSize;
        int plus = (this.totalNumber%this.pageSize) == 0 ? 0 : 1;
        totalPageTemp +=plus;
        if(totalPageTemp<=0){
            totalPageTemp =1;
        }
        this.totalPage = totalPageTemp;//总页数
        if(this.totalPage < this.currentPage){
            this.currentPage = this.totalPage;
        }
        if(this.currentPage<1){
            this.currentPage = 1;
        }
        this.startIndex = (this.currentPage-1)*this.pageSize;//起始位置等于之前所有页面数乘以页面大小
        this.totalSelect = this.pageSize;//检索数量等于页面大小
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值