欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mybatis 源码学习(二) Mapper 接口和sql的映射

程序员文章站 2022-07-12 22:37:17
...

问题:xml中的sql语句是怎么被映射到Mapper接口的一个方法上的?

弄明白了mapper是如何注册的了以后,发现xml文件中的namespace是关键。实际还是去找那个java接口文件。那么找到了接口文件,注册了mapper那这个mapper又是怎么反过来找到xml中配置的sql的呢?

看mapper注册的代码好想没有发现这个映射关系。从新再看一下源码,这次要顺利很很,很快找到了昨天那一串调用栈。

sqlSessionFactoryBuilder.build(inputStream);
return build(parser.parse());
parseConfiguration(parser.evalNode("/configuration"));
mapperElement(root.evalNode("mappers"));

然后找resource!=null的情况

 public void parse() {
    if (!configuration.isResourceLoaded(resource)) {
      configurationElement(parser.evalNode("/mapper"));//****关键的操作藏在了这里****
      configuration.addLoadedResource(resource);
      bindMapperForNamespace(); //这里就是去注册mapper的地方
    }

    parsePendingResultMaps();
    parsePendingChacheRefs();
    parsePendingStatements();
  }

  private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      sqlElement(context.evalNodes("/mapper/sql"));
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));//看到这里心里就大概明白了
    } catch (Exception e) {
      throw new RuntimeException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }

继续往下看呢,代码就很长了,注意到一点,这些配置并没有关联到mapper上,而是最终直接添加到了Configuration对象的

mappedStatements

mappedStatements 是一个map,而且他的key是namespace加id。

debug了一下:

Mybatis 源码学习(二) Mapper 接口和sql的映射

果然key就是"com.tiantao.learn.mappers.UserMapper.selectUser" namespace加上id。

同时还有一个只一个id,这两个都对应同一个对象。这么说来这个id应该是全局唯一的?!?!

记录一下调用栈

Mybatis 源码学习(二) Mapper 接口和sql的映射