This is the 16th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

In yesterday’s article, we covered the first five lines of the PageInterceptor code. Today we’ll look at PageInterceptor, the PageHelper interceptor.

The next line of code is:

Executor executor = (Executor) invocation.getTarget();
Copy the code

The Executor of the full path for org. Apache. Ibatis. Executor. Executor.

Executor is an Executor in Mybatis, which is an interface. Its inheritance structure relation in MyBatis can be expressed as follows:

Executor:
    -BaseExecutor:
        -SimpleExecutor
        -ReuseExeCutor
        -BatchExeCutor
    -CachingExecutor
Copy the code

An Executor’s main jobs include:

  1. Processing cache;
  2. Get database connection;
  3. createStatement
  4. Execute SQL statement
  5. Process SQL execution results

And from Executor, we find two Executor query methods:

public abstract <E> java.util.List<E> query(org.apache.ibatis.mapping.MappedStatement arg0, java.lang.Object arg1, org.apache.ibatis.session.RowBounds arg2, org.apache.ibatis.session.ResultHandler arg3, org.apache.ibatis.cache.CacheKey arg4, org.apache.ibatis.mapping.BoundSql arg5) throws java.sql.SQLException;
  
  public abstract <E> java.util.List<E> query(org.apache.ibatis.mapping.MappedStatement arg0, java.lang.Object arg1, org.apache.ibatis.session.RowBounds arg2, org.apache.ibatis.session.ResultHandler arg3) throws java.sql.SQLException;
  
Copy the code

According to PageHelper:

The query method with more arguments is called internally by the query method with fewer arguments

However, look further back at the code for PageInterceptor in PageHelper:

Executor executor = (Executor) invocation.getTarget();
CacheKey cacheKey;
BoundSql boundSql;
// Only one entry will be entered due to logic
if (args.length == 4) {
    //4 arguments
    boundSql = ms.getBoundSql(parameter);
    cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
} else {
    //6 parameters
    cacheKey = (CacheKey) args[4];
    boundSql = (BoundSql) args[5];
}
Copy the code

Where did the Args come from?

The interceptor method is the same as the one we used in PageHelper.

 Object[] args = invocation.getArgs();
Copy the code

The author also implemented a query method that blocks the Executor6 parameters.

Furthermore, this confirms that interceptors actually intercept Executor’s Query methods, sometimes with four arguments, sometimes with six arguments.

The most important lines of the following code:

// Intercepting boundSql
if (dialect instanceof BoundSqlInterceptor.Chain) {
    boundSql = ((BoundSqlInterceptor.Chain) dialect).doBoundSql(BoundSqlInterceptor.Type.ORIGINAL, boundSql, cacheKey);
}
List resultList;
// Call the method to determine whether paging is required, and return the result if not
if(! dialect.skip(ms, parameter, rowBounds)) {// Determine whether a count query is required
    if (dialect.beforeCount(ms, parameter, rowBounds)) {
        // Query the total number
        Long count = count(executor, ms, parameter, rowBounds, null, boundSql);
        // Process the total number of queries, return true to continue paging query, false directly return
        if(! dialect.afterCount(count, parameter, rowBounds)) {// If the total number of queries is 0, an empty result is returned
            return dialect.afterPage(newArrayList(), parameter, rowBounds); } } resultList = ExecutorUtil.pageQuery(dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);  }else {
    //rowBounds takes the parameter value and supports the default memory paging when not handled by the paging plug-in
    resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
}
Copy the code

After layer by layer judgment, when paging is needed, this is done:

resultList = ExecutorUtil.pageQuery(dialect, executor,
                        ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
Copy the code

This is the line of code that returns the result when paging is required. When you open the ExecutorUtil code, you can see that there is more or less an internal execution of various judgments, eventually executing executor.query. When is paging SQL inserted into the original SQL? So how does the code automatically change when paging?