Configuration--mappers--XMLMapperBuilder.parse(三-8-2)

本文详细解析了MyBatis中XMLMapperBuilder的parse方法如何处理XML文件,并生成MappedStatement对象。通过分析bindMapperForNamespace及configurationElement方法,揭示了namespace对应Class的绑定过程以及mapper标签下的子标签解析流程。

上一篇我们讲了ConfigurationaddMappers方法,可以看出,这个方法的最终目的,是将我们定义的mapper接口最终转化为MappedStatement,然后加入Configuration中,并且我们从上一篇文章中可以看出,即使我们是使用了class去配置mapper,也会去默认路径下加载xml文件.

本篇我们来看看当mapper标签加载的是一个xml文件时使用的XMLMapperBuilder.parse:

  public void parse() {
    // 看是否已经加载过该配置文件
    if (!configuration.isResourceLoaded(resource)) {
      // 解析mapper标签
      configurationElement(parser.evalNode("/mapper"));
      // 标识该xml文件已经被加载过
      configuration.addLoadedResource(resource);
      // 去加载对应的namespace对应的class
      bindMapperForNamespace();
    }

    // 这三个方法是重新加载一遍之前加载出错的标签
    parsePendingResultMaps();
    parsePendingChacheRefs();
    parsePendingStatements();
  }

我们先来看bindMapperForNamespace方法:

  // 在这个方法里,我们看到了熟悉的configuration.addMapper()方法,这说明在加载xml文件时,也会去解析一下namespace对应的class(如果该class存在的话)
  private void bindMapperForNamespace() {
    String namespace = builderAssistant.getCurrentNamespace();
    if (namespace != null) {
      Class<?> boundType = null;
      try {
        boundType = Resources.classForName(namespace);
      } catch (ClassNotFoundException e) {
        //ignore, bound type is not required
      }
      if (boundType != null) {
        if (!configuration.hasMapper(boundType)) {
          // Spring may not know the real resource name so we set a flag
          // to prevent loading again this resource from the mapper interface
          // look at MapperAnnotationBuilder#loadXmlResource
          configuration.addLoadedResource("namespace:" + namespace);
          configuration.addMapper(boundType);
        }
      }
    }
  }

接下来,我们再来看解析标签的configurationElement方法:

  // 从该方法中,我们可以看出,会逐步解析mapper标签下的子标签,具体解析过程,这里就不慢慢分析了,因为涉及到的细节过多,但是最终肯定是会生成一个MappedStatement的
  private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace.equals("")) {
          throw new BuilderException("Mapper's namespace cannot be empty");
      }
      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 BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }

至此,我们Configuration就分析完了,也成功的构建出了DefaultSqlSessionFactory,因为最终DefaultSqlSessionFactory中就只有一个Configuration:

  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

由于最后的mapper解析过程实在是复杂,所以本系列文章就简化了,之后如果有机会,博主会单开章节来写.

Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### The error may exist in mapper/BookMapper.xml ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/BookMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Mapper's namespace cannot be empty at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64) at Test.main(Test.java:18) Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/BookMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Mapper's namespace cannot be empty at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:122) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:99) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78) ... 2 more Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/BookMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Mapper's namespace cannot be empty at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:123) at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:95) at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:377) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:120) ... 4 more Caused by: org.apache.ibatis.builder.BuilderE
07-23
D:\Administrator\桌面\大上册\JAVAEE\jdk-17.0.12\bin\java.exe -javaagent:D:\Administrator\桌面\大上册\JAVAEE\ideaIU-2024.3.6.win\lib\idea_rt.jar=54940 -Dfile.encoding=UTF-8 -classpath D:\Administrator\桌面\大上册\JAVAEE\Workplace\exam1\ex7\m1-mybatis\target\test-classes;D:\Administrator\桌面\大上册\JAVAEE\Workplace\exam1\ex7\m1-mybatis\target\classes;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\junit\junit\4.13.2\junit-4.13.2.jar;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\org\mybatis\mybatis\3.5.19\mybatis-3.5.19.jar;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\com\mysql\mysql-connector-j\8.0.31\mysql-connector-j-8.0.31.jar;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\com\google\protobuf\protobuf-java\3.19.4\protobuf-java-3.19.4.jar;D:\Administrator\桌面\大上册\JAVAEE\mavenRepositories\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar Test Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### The error may exist in mapper/TitlesMapper.xml ### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/TitlesMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'com.example.po.Titles'. Cause: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:82) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:66) at Test.main(Test.java:15) Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/TitlesMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'com.example.po.Titles'. Cause: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:133) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:110) at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80) ... 2 more Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'mapper/TitlesMapper.xml'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'com.example.po.Titles'. Cause: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:125) at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:98) at org.apache.ibatis.builder.xml.XMLConfigBuilder.mappersElement(XMLConfigBuilder.java:405) at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:131) ... 4 more Caused by: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'com.example.po.Titles'. Cause: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:103) at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:105) at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildStatementFromContext(XMLMapperBuilder.java:141) at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildStatementFromContext(XMLMapperBuilder.java:133) at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:123) ... 7 more Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'com.example.po.Titles'. Cause: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:128) at org.apache.ibatis.builder.BaseBuilder.resolveAlias(BaseBuilder.java:132) at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:101) ... 11 more Caused by: java.lang.ClassNotFoundException: Cannot find class: com.example.po.Titles at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:226) at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:103) at org.apache.ibatis.io.Resources.classForName(Resources.java:322) at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:124) ... 13 more 进程已结束,退出代码为 1 为什么运行不了
最新发布
11-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值