mapper代理执行流程

87 阅读2分钟

mapper代理

mapper接口--->com.baomidou.mybatisplus.core.override.MybatisMapperProxy@76cdafa3

public final int insertBatchSomeColumn(List var1) throws  {
    try {
        return (Integer)super.h.invoke(this, m3, new Object[]{var1});
    } catch (RuntimeException | Error var3) {
        throw var3;
    } catch (Throwable var4) {
        throw new UndeclaredThrowableException(var4);
    }
}

h--->MybatisMapperProxy 执行方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        } else {
            return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
        }
    } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
    }
}

MapperMethodInvoker-->PlainMethodInvoker

    private static class PlainMethodInvoker implements MapperMethodInvoker {
        private final MybatisMapperMethod mapperMethod;

        public PlainMethodInvoker(MybatisMapperMethod mapperMethod) {
            super();
            this.mapperMethod = mapperMethod;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
            return mapperMethod.execute(sqlSession, args);
        }
    }

mapperMethod--->MybatisMapperMethod

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        switch (command.getType()) {
            case INSERT: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.insert(command.getName(), param));
                break;
            }
            case UPDATE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.update(command.getName(), param));
                break;
            }
            case DELETE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.delete(command.getName(), param));
                break;
            }
            case SELECT:
                if (method.returnsVoid() && method.hasResultHandler()) {
                    executeWithResultHandler(sqlSession, args);
                    result = null;
                } else if (method.returnsMany()) {
                    result = executeForMany(sqlSession, args);
                } else if (method.returnsMap()) {
                    result = executeForMap(sqlSession, args);
                } else if (method.returnsCursor()) {
                    result = executeForCursor(sqlSession, args);
                } else {
                    // TODO 这里下面改了
                    if (IPage.class.isAssignableFrom(method.getReturnType())) {
                        result = executeForIPage(sqlSession, args);
                        // TODO 这里上面改了
                    } else {
                        Object param = method.convertArgsToSqlCommandParam(args);
                        result = sqlSession.selectOne(command.getName(), param);
                        if (method.returnsOptional()
                            && (result == null || !method.getReturnType().equals(result.getClass()))) {
                            result = Optional.ofNullable(result);
                        }
                    }
                }
                break;
            case FLUSH:
                result = sqlSession.flushStatements();
                break;
            default:
                throw new BindingException("Unknown execution method for: " + command.getName());
        }
        if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
            throw new BindingException("Mapper method '" + command.getName()
                + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
        }
        return result;
    }

insert 方法

sqlSession【DefaultSqlSession】--->SqlSessionTemplate-代理类 代理类设置

  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {
    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
        new Class[] { SqlSession.class }, new SqlSessionInterceptor());
  }

方法执行

    public final int insert(String var1, Object var2) throws  {
        try {
            return (Integer)super.h.invoke(this, m9, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

h---->SqlSessionInterceptor【处理事务、线程安全之类】 juejin.cn/post/684490…

private class SqlSessionInterceptor implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
      try {
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator
              .translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }

目标方法:DefaultSqlSession.insert

  public int insert(String statement, Object parameter) {
    return update(statement, parameter);
  }
  public int update(String statement, Object parameter) {
    try {
      dirty = true;
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

executor【SimpleExecutor】--->代理类handler Plugin

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
  Set<Method> methods = signatureMap.get(method.getDeclaringClass());  
  if (methods != null && methods.contains(method)) {  
      return interceptor.intercept(new Invocation(target, method, args));  
  }  
  return method.invoke(target, args);  
}

interceptor--->MybatisPlusInterceptor

    public Object intercept(Invocation invocation) throws Throwable {
      Object target = invocation.getTarget();
      Object[] args = invocation.getArgs();
      if (target instanceof Executor) {
          final Executor executor = (Executor) target;
          Object parameter = args[1];
          boolean isUpdate = args.length == 2;
          MappedStatement ms = (MappedStatement) args[0];
          if (!isUpdate && ms.getSqlCommandType() == SqlCommandType.SELECT) {
              RowBounds rowBounds = (RowBounds) args[2];
              ResultHandler resultHandler = (ResultHandler) args[3];
              BoundSql boundSql;
              if (args.length == 4) {
                  boundSql = ms.getBoundSql(parameter);
              } else {
                  // 几乎不可能走进这里面,除非使用Executor的代理对象调用query[args[6]]
                  boundSql = (BoundSql) args[5];
              }
              for (InnerInterceptor query : interceptors) {
                  if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) {
                      return Collections.emptyList();
                  }
                  query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
              }
              CacheKey cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
              return executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
          } else if (isUpdate) {
              for (InnerInterceptor update : interceptors) {
                  if (!update.willDoUpdate(executor, ms, parameter)) {
                      return -1;
                  }
                  update.beforeUpdate(executor, ms, parameter);
              }
          }
      } else {
          // StatementHandler
          final StatementHandler sh = (StatementHandler) target;
          // 目前只有StatementHandler.getBoundSql方法args才为null
          if (null == args) {
              for (InnerInterceptor innerInterceptor : interceptors) {
                  innerInterceptor.beforeGetBoundSql(sh);
              }
          } else {
              Connection connections = (Connection) args[0];
              Integer transactionTimeout = (Integer) args[1];
              for (InnerInterceptor innerInterceptor : interceptors) {
                  innerInterceptor.beforePrepare(sh, connections, transactionTimeout);
              }
          }
      }
      return invocation.proceed();
  }

update 方法

 for (InnerInterceptor update : interceptors) {
  if (!update.willDoUpdate(executor, ms, parameter)) {
      return -1;
  }
  update.beforeUpdate(executor, ms, parameter);
}

PaginationInnerInterceptor CatMybatisPlugin 目标方法SimpleExecutor.doUpdate

  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
  Statement stmt = null;
  try {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
    stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.update(stmt);
  } finally {
    closeStatement(stmt);
  }