【Review】Mybatis-以PageHelper为例分析拦截器

1、背景

大家都知道,Mybatis提供了接口绑定,实现了DAO与xml文件的绑定,无需编写实现类,更方便使用。
但如果我们需要对某些语句进行额外的统一处理,且是在运行时动态修改,怎么办?
比如分页,不希望每次都在sql中手动填充分页参数,能不能动态传递分页参数来实现?

2、PageHelper

以PageHelper为例,来看下他是如果使用拦截器对sql进行处理的。


//其中,type:上面提到的四种拦截对象的类型。method:拦截哪些方法,因为是分页查询,所以只需要query即可。args:对应方法的参数。
@Intercepts(@Signature(type = Executor.class, method = "query", args = {
   MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class PageHelper implements Interceptor {
   

//方法增强
 public Object intercept(Invocation invocation) throws Throwable {
   
        if (autoRuntimeDialect) {
   
            SqlUtil sqlUtil = getSqlUtil(invocation);
            return sqlUtil.processPage(invocation);
        } else {
   
            if (autoDialect) {
   
                initSqlUtil(invocation);
            }
            return sqlUtil.processPage(invocation);
        }
  }

   /**
     * 只拦截Executor
     *
     * @param target
     * @return
     */
    public Object plugin(Object target) {
   
        if (target instanceof Executor) {
   
            return Plugin.wrap(target, this);
        } else {
   
            return target;
        }
    }
 }

其中intercept()主要处理逻辑在SqlUtil类中的doProcessPage(),主要逻辑是拦截boundSql,然后添加上分页的参数,最后将补充完整的sql语句进行执行。

 private Page doProcessPage(Invocation invocation, Page page, Object[] args) throws Throwable {
   
        //保存RowBounds状态
        RowBounds rowBounds = (RowBounds) args[2];
        //获取原始的ms
        MappedStatement ms = (MappedStatement) args[0];
        //判断并处理为PageSqlSource
        if (!isPageSqlSource(ms)) {
   
            processMappedStatement(ms);
        }
        //设置当前的parser,后面每次使用前都会set,ThreadLocal的值不会产生不良影响
        ((PageSqlSource)ms.getSqlSource()).setParser(parser);
        try {
   
            //忽略RowBounds-否则会进行Mybatis自带的内存分页
            args[2] = RowBounds.DEFAULT;
            //如果只进行排序 或 pageSizeZero的判断
            if (isQueryOnly(page)) {
   
                return doQueryOnly(page, invocation);
            }

            //简单的通过total的值来判断是否进行count查询
            if (page.isCount()) {
   
                page.setCountSignal(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值