MyBatis 源码浅析

139 阅读2分钟

MyBatis是一款半自动化的ORM(Object Relational Mapping:对象关系映射)框架,能够将数据库中的记录转换为Java实体。框架会做帮我们做如下的一些映射:

数据库的表(table) --> 类(class)
记录(record,行数据)--> 对象(object)
字段(field)--> 对象的属性(attribute)

这篇文章会通过源码分析MyBatis配置文件的加载与解析流程。

MyBatis配置及其使用回顾

在分析具体的加载流程前,我们先来回顾一下MyBatis的使用步骤: 1、一般情况我们会有一个主配置文件,当中配置了数据库连接信息,数据库表对应实体类别名,类型处理器,插件,SQL映射文件Mapper.xml等信息。文件以configuration标签开头。标签如下所示(具体的配置(略)):

<configuration>
  <properties resource=""/>
<!--是否使用缓存、懒加载、自动生成主键等配置-->
  <settings></settings>
<!--实体类别名配置-->
  <typeAliases></typeAliases>
<!--类型处理器配置-->
  <typeHandlers></typeHandlers>
<!--插件配置-->
  <plugins></plugins>
<!--相关环境配置,包括数据库连接等信息-->
  <environments default="development"></environments>
<!--Mapper文件信息配置-->
  <mappers></mappers>
</configuration>

2、编写数据库表对应的实体类,将数据库表字段映射成Java类中的属性。 3、编写Mapper接口和对应的Mapper.xml文件,并在Mapper当中书写相应的SQL语句。以下是Mapper文件中的相关标签及其作用:

<!--namespace:所对应的Mapper接口-->
<mapper namespace="org.apache.ibatis.domain.blog.mappers.AuthorMapper">
<!--查询参数Map-->
 <parameterMap> </parameterMap>
<!--结果集字段映射-->
 <resultMap></resultMap>
<!--SQL语句-->
 <select id="selectAllAuthorsLinkedList" resultType="org.apache.ibatis.domain.blog.Author">
        select * from author
 </select>
</mapper>

配置文件的加载与解析流程

在日常开发中,我们也会发现在程序启动时会先将以上的配置文件先加载到内存并进行解析。可以通过MyBatis的一段单元测试来了解其中的流程:

  private static SqlSessionFactory sqlSessionFactory;

  @BeforeAll
  static void setUp() throws Exception {
    // create a SqlSessionFactory 
    try (
        Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/no_param_type/mybatis-config.xml"));
      sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    }

    // populate in-memory database
    BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
        "org/apache/ibatis/submitted/no_param_type/CreateDB.sql");
  }

可以看出大致的流程如下: 将主配置文件加载进内存,生成字符流-->使用XPath对XML进行解析,转成可解析的XMLConfigBuilder对象-->将信息解析成Configuration对象。通过配置信息Configuration构建SqlSessionFactory对象。

  • 具体的调用链如下:
//1、生成XMLConfigBuilder对象(主要使用工具对xml文件进行解析):包含Document文档对象
 XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
//2、解析配置文件,生成Configuration对象
  public Configuration parse() {
    ...部分代码省略...
    //标签解析
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }
//对各种标签的解析与处理代码
 private void parseConfiguration(XNode root) {
    try {
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
//对Mappers标签进行解析
  mapperElement(root.evalNode("mappers"));
...部分代码省略...
}
//对Mapper.xml文件进行解析,并注册Mapper文件信息
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
configurationElement(parser.evalNode("/mapper"));
configuration.addMapper(boundType);

总结:xml文件配置信息经过加载,解析,最终会解析成Configuration对象以供程序后续的使用。

image.png