MyBatis-Plus源码分析(一)基本请求流程

Mybatis plus是近两年比较流行的框架,在一个方法执行的时候实际上是进入了MapperProxy的invoke方法,如果是查询,一路下去,后面进入了RoutingStatementHandler的query()方法。

一、NativeMethodAccessorImpl

在后面会发现调用method.invoke()方法的时候,都进入了NativeMethodAccessorImpl方法中,这个类中有个native,很多人看源码的时候,觉得源码到这个地方就结束了,native方法是去调用本地方法了,后面就查看不了了。其实NativeMethodAccessorImpl.invoke0()是java发射类的一个方法,后面调用的还是你的java代码,其原理如下:JAVA深入研究——Method的Invoke方法,关于asm反射性能:ASM 高性能的反射

二、返回类型的确定

在mybatis plus中都是一水的实体类返回,没看到返回单个字段的,这是为什么呢,在填充返回类型的时候mybatis plus用到了一个类BaseTypeHandler,这个类是在填充返回参数的时候使用的,其子类有LongTypeHandler,IntegerTyperHandler等多种,关于是那种类型的TypeHandler,是从DefaultResultSetHandler中获取的:

  @Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

其中的resultMaps是从mappedStatement中获取到的。它的初始化是在服务启动的时候,MapperBuilderAssistant中:

  public MappedStatement addMappedStatement(
      String id,
      SqlSource sqlSource,
      StatementType statementType,
      SqlCommandType sqlCommandType,
      Integer fetchSize,
      Integer timeout,
      String parameterMap,
      Class<?> parameterType,
      String resultMap,
      Class<?> resultType,
      ResultSetType resultSetType,
      boolean flushCache,
      boolean useCache,
      boolean resultOrdered,
      KeyGenerator keyGenerator,
      String keyProperty,
      String keyColumn,
      String databaseId,
      LanguageDriver lang,
      String resultSets) {

    if (unresolvedCacheRef) {
      throw new IncompleteElementException("Cache-ref not yet resolved");
    }

    id = applyCurrentNamespace(id, false);
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
        .resource(resource)
        .fetchSize(fetchSize)
        .timeout(timeout)
        .statementType(statementType)
        .keyGenerator(keyGenerator)
        .keyProperty(keyProperty)
        .keyColumn(keyColumn)
        .databaseId(databaseId)
        .lang(lang)
        .resultOrdered(resultOrdered)
        .resultSets(resultSets)
        .resultMaps(getStatementResultMaps(resultMap, resultType, id))
        .resultSetType(resultSetType)
        .flushCacheRequired(valueOrDefault(flushCache, !isSelect))
        .useCache(valueOrDefault(useCache, isSelect))
        .cache(currentCache);

    ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
    if (statementParameterMap != null) {
      statementBuilder.parameterMap(statementParameterMap);
    }

    MappedStatement statement = statementBuilder.build();
    configuration.addMappedStatement(statement);
    return statement;
  }

MyBatis-Plus源码分析(一)基本请求流程

三、17种sql

在mybatis plus中默认的sql有17种,如下MyBatis-Plus源码分析(一)基本请求流程
如果以SelectMaps为例:

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        SqlMethod sqlMethod = SqlMethod.SELECT_MAPS;
        String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true),
            tableInfo.getTableName(), this.sqlWhereEntityWrapper(true, tableInfo));
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class, tableInfo);
    }

其返回类型都已经定义好了,MyBatis-Plus源码分析(一)基本请求流程
如果要自己定义返回类型,就要自己去写自己定义的类。