Mybatis源码分析1--创建会话与配置文件解析

mybatis的基础使用类似下面的代码

    public static void main(String[] args) throws IOException {
        InputStream is = Resources.getResourceAsStream("");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        mapper.findAll();
        sqlSession.close();
    }

这一篇分析mybatis构建SqlSessionFactory的源码分析,其中包括创建SqlSessionFactory和其相关的配置文件,mapper的解析,本篇有点长

使用了builder构造SqlSessionFactory

  //org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream)
  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }
  //org.apache.ibatis.session.SqlSessionFactoryBuilder#build
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //创建一个解析器,用来解析配置文件,sql的xml文件
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //解析xml文件,并且构建SqlSessionFactory
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  //org.apache.ibatis.session.SqlSessionFactoryBuilder#build
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
  
  //org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
  private final Configuration configuration;

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }

配置文件的解析

创建解析器

  //org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder
  public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
  }
  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
  }

  //调用XMLConfigBuilder抽象父类BaseBuilder的构造器
  //org.apache.ibatis.builder.BaseBuilder#BaseBuilder
  //这个类只有这三个属性
  public BaseBuilder(Configuration configuration) {
    this.configuration = configuration;
    this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
    this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
  }

创建Configration,Configration的构造器以及一些属性

  //Configration的一些属性
  //mybatis环境
  protected Environment environment;
  //用来生成mapper
  protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
  //拦截器链,插件用拦截器实现
  protected final InterceptorChain interceptorChain = new InterceptorChain();
  //类型处理器注册
  protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this);
  //别名注册
  protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
  protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
  //sql配置
  protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
  //缓存
  protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
  //结果集
  protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
  //参数集
  protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
  //主键生成器
  protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<>("Key Generators collection");

  protected final Set<String> loadedResources = new HashSet<>();
  protected final Map<String, XNode> sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers");

  protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<>();
  protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<>();
  protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<>();
  protected final Collection<MethodResolver> incompleteMethods = new LinkedList<>();
  //Configration构造器
  public Configuration() {
    // 为类型注册别名
    typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
    typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

    typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
    typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
    typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);

    typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
    typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
    typeAliasRegistry.registerAlias("LRU", LruCache.class);
    typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
    typeAliasRegistry.registerAlias("WEAK", WeakCache.class);

    typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);

    typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
    typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);

    typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
    typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
    typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
    typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
    typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
    typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
    typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

    typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
    typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);

    languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
    languageRegistry.register(RawLanguageDriver.class);
  }

解析xml文件

  //org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
  public Configuration parse() {
    //解析过了,抛异常
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    //标记已经解析过了
    parsed = true;
    //解析配置,传入根元素
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

解析配置

  //org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
  private void parseConfiguration(XNode root) {
    try {
      //解析配置文件各种标签
      propertiesElement(root.evalNode("properties"));
      //解析setting标签
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      //解析别名
      typeAliasesElement(root.evalNode("typeAliases"));
      //解析插件
      pluginElement(root.evalNode("plugins"));
      //解析对象工厂
      objectFactoryElement(root.evalNode("objectFactory"));
      //对象加工
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      //反射
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      //给setting的子标签赋值
      settingsElement(settings);
      //创建数据源
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      //解析类型处理器
      typeHandlerElement(root.evalNode("typeHandlers"));
      //解析mapper
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }
创建数据源
  //org.apache.ibatis.builder.xml.XMLConfigBuilder#environmentsElement
  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          // 事务工厂
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          // 数据源工厂
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          // 数据源
          DataSource dataSource = dsFactory.getDataSource();
          // 包含了 事务工厂和数据源的 Environment
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          // 放入 Configuration
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

  //创建数据源工厂
  //org.apache.ibatis.builder.xml.XMLConfigBuilder#dataSourceElement
  private DataSourceFactory dataSourceElement(XNode context) throws Exception {
    if (context != null) {
      //dataSource标签的子标签
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      //根据具体类型实例化数据源工厂
      DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a DataSourceFactory.");
  }

  //获取数据源工厂的具体类型
  //org.apache.ibatis.builder.BaseBuilder#resolveClass
  protected <T> Class<? extends T> resolveClass(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return resolveAlias(alias);
    } catch (Exception e) {
      throw new BuilderException("Error resolving class. Cause: " + e, e);
    }
  }
  //从别名注册器中获取具体的类型
  //org.apache.ibatis.builder.BaseBuilder#resolveAlias
  protected <T> Class<? extends T> resolveAlias(String alias) {
    return typeAliasRegistry.resolveAlias(alias);
  }
解析typeHandlers标签,注册typeHandler
  //org.apache.ibatis.builder.xml.XMLConfigBuilder#typeHandlerElement
  private void typeHandlerElement(XNode parent) {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String typeHandlerPackage = child.getStringAttribute("name");
          typeHandlerRegistry.register(typeHandlerPackage);
        } else {
          //Java类型名称
          String javaTypeName = child.getStringAttribute("javaType");
          //jdbc类型名称
          String jdbcTypeName = child.getStringAttribute("jdbcType");
          //类型处理器名称
          String handlerTypeName = child.getStringAttribute("handler");
          Class<?> javaTypeClass = resolveClass(javaTypeName);
          JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
          Class<?> typeHandlerClass = resolveClass(handlerTypeName);
          if (javaTypeClass != null) {
            //注册类型处理器
            if (jdbcType == null) {
              typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
            } else {
              typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
            }
          } else {
            typeHandlerRegistry.register(typeHandlerClass);
          }
        }
      }
    }
  }
解析mapper
  //org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement
  private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        // package	包
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            // resource	相对路径
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            // 解析 Mapper.xml,总体上做了两件事情 >>
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            // url	绝对路径
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            // class 	单个接口
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }
根据包名注册mapper
  //org.apache.ibatis.session.Configuration#addMappers(java.lang.String)
  public void addMappers(String packageName) {
    mapperRegistry.addMappers(packageName);
  }
  //org.apache.ibatis.binding.MapperRegistry#addMappers(java.lang.String)
  public void addMappers(String packageName) {
    addMappers(packageName, Object.class);
  }
  //org.apache.ibatis.binding.MapperRegistry#addMappers
  public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    //从包中获取所有的mapper
    Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    // 循环添加
    for (Class<?> mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }
添加mapper
  //org.apache.ibatis.binding.MapperRegistry#addMapper
  public <T> void addMapper(Class<T> type) {
    //只有接口才会被处理
    if (type.isInterface()) {
      //已经添加过该mapper了
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        //private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
        //存放的是接口类型,和对应的工厂类的关系
        knownMappers.put(type, new MapperProxyFactory<>(type));
		//mapper类型注册应该早于mapper的解析
        // 注册了接口之后,根据接口,开始解析所有方法上的注解,例如 @Select >>
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }
解析mapper
  //org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse
  public void parse() {
    String resource = type.toString();
    if (!configuration.isResourceLoaded(resource)) {
      // 先判断 Mapper.xml 有没有解析,没有的话先解析 Mapper.xml(例如定义 package 方式)
      loadXmlResource();
      configuration.addLoadedResource(resource);
      assistant.setCurrentNamespace(type.getName());
      // 处理 @CacheNamespace
      parseCache();
      // 处理 @CacheNamespaceRef
      parseCacheRef();
      // 获取所有方法
      Method[] methods = type.getMethods();
      for (Method method : methods) {
        try {
          // issue #237
          if (!method.isBridge()) {
            // 解析方法上的注解,添加到 MappedStatement 集合中 >>
            parseStatement(method);
          }
        } catch (IncompleteElementException e) {
          configuration.addIncompleteMethod(new MethodResolver(this, method));
        }
      }
    }
    parsePendingMethods();
  }
加载mapper.xml资源
  //org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#loadXmlResource
  private void loadXmlResource() {
    // Spring 不知道真正的资源名字,所以添加了一个标志防止资源被加载两次
    // 标记在这里 XMLMapperBuilder#bindMapperForNamespace
    if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
      String xmlResource = type.getName().replace('.', '/') + ".xml";
      // #1347  加载mapper.xml
      InputStream inputStream = type.getResourceAsStream("/" + xmlResource);
      if (inputStream == null) {
        // 从classpath下加载mapper.xml
        try {
          inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
        } catch (IOException e2) {
          // ignore, resource is not required
        }
      }
      if (inputStream != null) {
        //构建mapper解析器
        XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
        // 解析 Mapper.xml >>
        xmlParser.parse();
      }
    }
  }
解析mappe.xml
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
  public void parse() {
    // 资源还没有被加载
    //protected final Set<String> loadedResources = new HashSet<>();
    if (!configuration.isResourceLoaded(resource)) {
      // 具体增删改查标签的解析。 一个标签一个MappedStatement
      configurationElement(parser.evalNode("/mapper"));
      //标记该资源已经被加载
      configuration.addLoadedResource(resource);
      // 2、把namespace(接口类型)和工厂类绑定起来,放到一个map。
      // 一个namespace 一个 MapperProxyFactory >>
      bindMapperForNamespace();
    }

    parsePendingResultMaps();
    parsePendingCacheRefs();
    parsePendingStatements();
  }
解析mapper标签
  private void configurationElement(XNode context) {
    try {
      //解析namespace
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      builderAssistant.setCurrentNamespace(namespace);
      // 添加缓存对象
      cacheRefElement(context.evalNode("cache-ref"));
      // 解析 cache 属性,添加缓存对象
      cacheElement(context.evalNode("cache"));
      // 创建 ParameterMapping 对象
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      // 创建 List<ResultMapping>
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      // 解析可以复用的SQL
      sqlElement(context.evalNodes("/mapper/sql"));
      // 解析增删改查标签,得到 MappedStatement
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }
创建 ParameterMapping 对象
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#parameterMapElement
  private void parameterMapElement(List<XNode> list) {
    for (XNode parameterMapNode : list) {
      //获取id
      String id = parameterMapNode.getStringAttribute("id");
      //获取type
      String type = parameterMapNode.getStringAttribute("type");
      //解析type对应的类
      Class<?> parameterClass = resolveClass(type);
      //获取参数类型
      List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
      List<ParameterMapping> parameterMappings = new ArrayList<>();
      //循环遍历所有的参数
      for (XNode parameterNode : parameterNodes) {
        //获取属性名称
        String property = parameterNode.getStringAttribute("property");
        //获取Java类型
        String javaType = parameterNode.getStringAttribute("javaType");
        //获取jdbc类型
        String jdbcType = parameterNode.getStringAttribute("jdbcType");
        //获取resultMap的名称
        String resultMap = parameterNode.getStringAttribute("resultMap");
        //获取模式
        String mode = parameterNode.getStringAttribute("mode");
        //获取类型处理器
        String typeHandler = parameterNode.getStringAttribute("typeHandler");
        Integer numericScale = parameterNode.getIntAttribute("numericScale");
        //解析模式枚举	IN, OUT, INOUT
        ParameterMode modeEnum = resolveParameterMode(mode);
        //解析Java类型的类
        Class<?> javaTypeClass = resolveClass(javaType);
        //解析jdbc类型的类
        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
        //解析类型处理器的类
        Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
        //建立parameterMapping并加入parameterMappings
        ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
        parameterMappings.add(parameterMapping);
      }
      builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
    }
  }
  //添加parameterMap
  //protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
  //org.apache.ibatis.builder.MapperBuilderAssistant#addParameterMap
  public ParameterMap addParameterMap(String id, Class<?> parameterClass, List<ParameterMapping> parameterMappings) {
    id = applyCurrentNamespace(id, false);
    ParameterMap parameterMap = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings).build();
    configuration.addParameterMap(parameterMap);
    return parameterMap;
  }
创建resultMappings
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElements
  private void resultMapElements(List<XNode> list) {
    for (XNode resultMapNode : list) {
      try {
        resultMapElement(resultMapNode);
      } catch (IncompleteElementException e) {
        // ignore, it will be retried
      }
    }
  }
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElement
  private ResultMap resultMapElement(XNode resultMapNode) {
    return resultMapElement(resultMapNode, Collections.emptyList(), null);
  }
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElement
  private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) {
    ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
    //获取四中之一的名称
    String type = resultMapNode.getStringAttribute("type",
        resultMapNode.getStringAttribute("ofType",
            resultMapNode.getStringAttribute("resultType",
                resultMapNode.getStringAttribute("javaType"))));
    //解析类型
    Class<?> typeClass = resolveClass(type);
    if (typeClass == null) {
      typeClass = inheritEnclosingType(resultMapNode, enclosingType);
    }
    Discriminator discriminator = null;
    List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
    List<XNode> resultChildren = resultMapNode.getChildren();
    //循环遍历子节点
    for (XNode resultChild : resultChildren) {
      if ("constructor".equals(resultChild.getName())) {
        processConstructorElement(resultChild, typeClass, resultMappings);
      } else if ("discriminator".equals(resultChild.getName())) {
        discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
      } else {
        List<ResultFlag> flags = new ArrayList<>();
        if ("id".equals(resultChild.getName())) {
          flags.add(ResultFlag.ID);
        }
        //构建resuntMapping并添加到resultMappings
        resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
      }
    }
    //获取id
    String id = resultMapNode.getStringAttribute("id",
            resultMapNode.getValueBasedIdentifier());
    String extend = resultMapNode.getStringAttribute("extends");
    Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
    //生成resultMapping解析器
    ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
    try {
      return resultMapResolver.resolve();
    } catch (IncompleteElementException  e) {
      configuration.addIncompleteResultMap(resultMapResolver);
      throw e;
    }
  }
  //org.apache.ibatis.builder.ResultMapResolver#resolve
  public ResultMap resolve() {
    return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping);
  }
  //添加resultMap
  //org.apache.ibatis.builder.MapperBuilderAssistant#addResultMap
  public ResultMap addResultMap(
      String id,
      Class<?> type,
      String extend,
      Discriminator discriminator,
      List<ResultMapping> resultMappings,
      Boolean autoMapping) {
    id = applyCurrentNamespace(id, false);
    extend = applyCurrentNamespace(extend, true);

    if (extend != null) {
      if (!configuration.hasResultMap(extend)) {
        throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'");
      }
      ResultMap resultMap = configuration.getResultMap(extend);
      List<ResultMapping> extendedResultMappings = new ArrayList<>(resultMap.getResultMappings());
      extendedResultMappings.removeAll(resultMappings);
      // Remove parent constructor if this resultMap declares a constructor.
      boolean declaresConstructor = false;
      for (ResultMapping resultMapping : resultMappings) {
        if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
          declaresConstructor = true;
          break;
        }
      }
      if (declaresConstructor) {
        extendedResultMappings.removeIf(resultMapping -> resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR));
      }
      resultMappings.addAll(extendedResultMappings);
    }
    ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping)
        .discriminator(discriminator)
        .build();
    configuration.addResultMap(resultMap);
    return resultMap;
  }
  //org.apache.ibatis.session.Configuration#addResultMap
  //protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
  public void addResultMap(ResultMap rm) {
    resultMaps.put(rm.getId(), rm);
    checkLocallyForDiscriminatedNestedResultMaps(rm);
    checkGloballyForDiscriminatedNestedResultMaps(rm);
  }
创建Statement
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext
  private void buildStatementFromContext(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
      buildStatementFromContext(list, configuration.getDatabaseId());
    }
    // 解析 Statement
    buildStatementFromContext(list, null);
  }
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext
  private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
    for (XNode context : list) {
      // 用来解析增删改查标签的 XMLStatementBuilder
      final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
      try {
        // 解析 Statement,添加 MappedStatement 对象
        statementParser.parseStatementNode();
      } catch (IncompleteElementException e) {
        configuration.addIncompleteStatement(statementParser);
      }
    }
  }
  //org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
  public void parseStatementNode() {
  	//获取id
    String id = context.getStringAttribute("id");
    //获取databaseId
    String databaseId = context.getStringAttribute("databaseId");

    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
      return;
    }

    String nodeName = context.getNode().getNodeName();
    //获取sql类型
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    //是否是查询语句
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    //不是查询,要刷新缓存
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    //是查询,要使用缓存
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    //结果是否排序,默认否
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

    // Include Fragments before parsing
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    includeParser.applyIncludes(context.getNode());

	//参数类型
    String parameterType = context.getStringAttribute("parameterType");
    //解析参数类型
    Class<?> parameterTypeClass = resolveClass(parameterType);

	//语言
    String lang = context.getStringAttribute("lang");
    LanguageDriver langDriver = getLanguageDriver(lang);

    // 解析selectkey,之后是用并删除
    processSelectKeyNodes(id, parameterTypeClass, langDriver);

    // 解析sql
    KeyGenerator keyGenerator;
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    if (configuration.hasKeyGenerator(keyStatementId)) {
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
    }

    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    //statement的类型,默认PreparedStatement
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String resultType = context.getStringAttribute("resultType");
    Class<?> resultTypeClass = resolveClass(resultType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultSetType = context.getStringAttribute("resultSetType");
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
    if (resultSetTypeEnum == null) {
      resultSetTypeEnum = configuration.getDefaultResultSetType();
    }
    //主键的名称
    String keyProperty = context.getStringAttribute("keyProperty");
    //主键的列名
    String keyColumn = context.getStringAttribute("keyColumn");
    String resultSets = context.getStringAttribute("resultSets");

    // 创建 MappedStatement 
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
  }
  //org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement
  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
    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
    MappedStatement statement = statementBuilder.build();
    // 在 Configuration 添加 MappedStatement
    configuration.addMappedStatement(statement);
    return statement;
  }
  //org.apache.ibatis.session.Configuration#addMappedStatement
  //protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
  public void addMappedStatement(MappedStatement ms) {
    mappedStatements.put(ms.getId(), ms);
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值