Mybatis源码分析六

本文详细分析了 MyBatis 如何从 Mapper XML 文件中读取 SQL 语句,并在执行前进行参数映射的过程。在解析 XML 时,SQL 语句在构建 SqlSessionFactory 时被存入 Configuration 的 mappedStatements 中。在执行 SQL 时,MyBatis 通过动态代理获取 Connection 和 PreparedStatement,然后利用 TypeHandler 进行参数映射。
摘要由CSDN通过智能技术生成

在前面的探索中,我们已经知道了 MyBatis 是如何 getMapper 并执行 Mapper 接口中的方法来进行数据库操作的。那么今天我们就来看看 Mapper 方法执行的“前因”:获取语句+参数映射。
我们还是按照之前的方式,使用 debug 在入口代码上打断点,步入源码。入口代码为:

List<Author> list = mapper.selectByName("Sylvia");
    <select id="selectByName" resultMap="AuthorMap" >
        select
          id, name, sex, phone
        from author
        where name = #{
   name}
    </select>
从 Mapper XML 读取 SQL

首先,我们要思考一下,因为 SQL 语句是定义在 Mapper XML 中的,那么毫无疑问它会去读取该 Mapper XML 中的内容。可是它会在什么时候读取呢?答案是在获取 SqlSessionFactory 的时候,即执行

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);  

为了验证,我们可以在这行打个断点来一探究竟。

我们一直往下走,直到 org.apache.ibatis.builder.xml.XMLConfigBuilder 的 parseConfiguration 方法,我们在之前已经见过这个方法了,它的作用是解析 mybatis-config.xml 文件中的配置,将相应的元素内容转换到 Configuration 等类中:

  private void parseConfiguration(XNode root) {
   
    try {
   
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      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"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
   
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

我们要看的是 Mapper XML 中 SQL 是不是在这个地方读取的,理所应当进入最后一行解析代码:mapperElement(root.evalNode(“mappers”));。这个时候我们会进入到 org.apache.ibatis.builder.xml.XMLConfigBuilder 的 mapperElement 方法:

  private void mapperElement(XNode parent) throws Exception {
   
    if (parent != null) {
   
      for (XNode child : parent.getChildren()) {
   
        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) {
   
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          }//略...
        }
      }
    }
  }

在这个方法中我们可以看到它在解析 mybatis-config.xml 中的 mappers 元素内容。注意最后一行代码:mapperParser.parse(); 看名字它似乎就是想要去解析 Mapper XML 的内容,进入 org.apache.ibatis.builder.xml.XMLMapperBuilder 的 parse() 方法:

  public void parse() {
   
    if (
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值