栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 mappedStatements = new StrictMap("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
  //缓存
  protected final Map caches = new StrictMap<>("Caches collection");
  //结果集
  protected final Map resultMaps = new StrictMap<>("Result Maps collection");
  //参数集
  protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection");
  //主键生成器
  protected final Map keyGenerators = new StrictMap<>("Key Generators collection");

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

  protected final Collection incompleteStatements = new linkedList<>();
  protected final Collection incompleteCacheRefs = new linkedList<>();
  protected final Collection incompleteResultMaps = new linkedList<>();
  protected final Collection 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  Class 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  Class 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> resolverUtil = new ResolverUtil<>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    //从包中获取所有的mapper
    Set>> mapperSet = resolverUtil.getClasses();
    // 循环添加
    for (Class mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }
添加mapper
  //org.apache.ibatis.binding.MapperRegistry#addMapper
  public  void addMapper(Class 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, 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 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
      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 list) {
    for (XNode parameterMapNode : list) {
      //获取id
      String id = parameterMapNode.getStringAttribute("id");
      //获取type
      String type = parameterMapNode.getStringAttribute("type");
      //解析type对应的类
      Class parameterClass = resolveClass(type);
      //获取参数类型
      List parameterNodes = parameterMapNode.evalNodes("parameter");
      List 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> 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 parameterMaps = new StrictMap<>("Parameter Maps collection");
  //org.apache.ibatis.builder.MapperBuilderAssistant#addParameterMap
  public ParameterMap addParameterMap(String id, Class parameterClass, List 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 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 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 resultMappings = new ArrayList<>(additionalResultMappings);
    List 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 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 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 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 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 list) {
    if (configuration.getDatabaseId() != null) {
      buildStatementFromContext(list, configuration.getDatabaseId());
    }
    // 解析 Statement
    buildStatementFromContext(list, null);
  }
  //org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext
  private void buildStatementFromContext(List 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 mappedStatements = new StrictMap("Mapped Statements collection")
      .conflictMessageProducer((savedValue, targetValue) ->
          ". please check " + savedValue.getResource() + " and " + targetValue.getResource());
  public void addMappedStatement(MappedStatement ms) {
    mappedStatements.put(ms.getId(), ms);
  }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/683675.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号