1. 程式人生 > >Mybatis 原始碼學習(二) Mapper 介面和sql的對映

Mybatis 原始碼學習(二) Mapper 介面和sql的對映

問題: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了一下:


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

同時還有一個只一個id,這兩個都對應同一個物件。這麼說來這個id應該是全域性唯一的?!?!

記錄一下呼叫棧