水煮MyBatis(三)- SQL解析

前言

在Mapper接口中,有注解的方法,也有xml配置的方法,这一章我们主要介绍前者。

本文介绍的Mapper方法

    @Select("select * from tb_image where md5 = #{md5}")
    ImageInfo byMd5(@Param(value = "md5") String md5);

序列图

image.png

注册Mapper

注册Mapper,将Mapper注册到knownMappers中,注意后面的是一个代理类,后续再开个单章介绍。同时将Mapper接口解析,代码中的config参数是Configuration的实体,主要是mybatis的配置信息。


  public <T> void addMapper(Class<T> type) {
        // 注册
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // 主要代码就是这两行
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        // 解析
        parser.parse();
  }

image.png

解析Mapper

Mapper里的每个方法都会创建一个statement,供后续执行使用。

解析Mapper中的方法

  public void parse() {
    String resource = type.toString();
    // 加载xml配置,在XMLMapperBuilder中解析xml中的方法,这里忽略不讲
    loadXmlResource();
    // 每个Mapper加载一次
    configuration.addLoadedResource(resource);
    // 当前Mapper的命名空间
    assistant.setCurrentNamespace(type.getName());
    // 缓存注解解析,见后续单章
    parseCache();
    parseCacheRef();
    // 每个方法都需要生成一个statement
    for (Method method : type.getMethods()) {
      // 忽略不能解析的方法,比如抽象、静态等
      if (!canHaveStatement(method)) {
          continue;
      }
      // 生成statement,保存到configuration
      parseStatement(method);
    }
  }

主要流程分为三个步骤:

  • 解析Mapper对应的xml文件,并为xml文件里的每个方法都生成一个statement;
  • 解析缓存注解,后续介绍;
  • 解析注解方法;

生成statement

    public MappedStatement addMappedStatement(...) {
    // 是否查询方法
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    // 生成statement
    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);
    }
    // Mapper里每个方法都会生成一个statement
    MappedStatement statement = statementBuilder.build();
    // 将statement放到mybatis上下文
    configuration.addMappedStatement(statement);
    return statement;
  }

将statement注册到Configuration里的mappedStatements结构中,后续执行的时候,直接从这里获取对应方法的statement

public void addMappedStatement(MappedStatement ms) {
    mappedStatements.put(ms.getId(), ms);
  }

替换sql中的占位符

在SqlSourceBuilder类中,对sql中的参数占位符进行替换

  public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
    ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
    GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
    String sql;
    if (configuration.isShrinkWhitespacesInSql()) {
      sql = parser.parse(removeExtraWhitespaces(originalSql));
    } else {
      sql = parser.parse(originalSql);
    }
    // 从handler中获取请求参数map
    return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
  }

例子中的请求参数:
ParameterMapping{property='md5', mode=IN, javaType=class java.lang.String, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}
替换效果如下:
image.png

最终Statement信息

image.png

全部评论

相关推荐

尊尼获获:闺蜜在哪?
点赞 评论 收藏
分享
评论
点赞
收藏
分享
正在热议
# 25届秋招总结 #
442240次浏览 4509人参与
# 春招别灰心,我们一人来一句鼓励 #
41913次浏览 531人参与
# 阿里云管培生offer #
120209次浏览 2219人参与
# 地方国企笔面经互助 #
7961次浏览 18人参与
# 同bg的你秋招战况如何? #
76585次浏览 561人参与
# 虾皮求职进展汇总 #
115499次浏览 886人参与
# 北方华创开奖 #
107422次浏览 599人参与
# 实习,投递多份简历没人回复怎么办 #
2454609次浏览 34856人参与
# 实习必须要去大厂吗? #
55761次浏览 961人参与
# 提前批简历挂麻了怎么办 #
149889次浏览 1977人参与
# 投递实习岗位前的准备 #
1195913次浏览 18548人参与
# 你投递的公司有几家约面了? #
33203次浏览 188人参与
# 双非本科求职如何逆袭 #
662189次浏览 7394人参与
# 如果公司给你放一天假,你会怎么度过? #
4751次浏览 55人参与
# 机械人春招想让哪家公司来捞你? #
157622次浏览 2267人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11535次浏览 284人参与
# 发工资后,你做的第一件事是什么 #
12682次浏览 62人参与
# 工作中,努力重要还是选择重要? #
35793次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20120次浏览 240人参与
# 我的上岸简历长这样 #
452000次浏览 8088人参与
# 实习想申请秋招offer,能不能argue薪资 #
39289次浏览 314人参与
# 非技术岗是怎么找实习的 #
155866次浏览 2120人参与
牛客网
牛客企业服务