MyBatis 是一款半自动化的 ORM(Object Relational Mapping:对象关系映射)框架,帮我们消除了大量的 JDBC 冗余代码,包括参数的设置,结果集的封装等,能够将数据库中的记录转换为 Java 实体。这篇文章会通过源码的角度分析 MyBatis 加载配置文件的流程。
先通过一张图来看看 MyBatis 是如何运行的吧:

在这过程中,MyBatis 会帮我们处理数据库表与 Java 实体的映射关系:
1 2 3
| 数据库的表(table) --> 类(class) 记录(record,行数据)--> 对象(object) 字段(field)--> 对象的属性(attribute)
|
MyBatis 当中的配置及其使用回顾
在分析具体的加载流程前,我们先来回顾一下 MyBatis 的使用步骤:
1、一般情况我们会有一个主配置文件,当中配置了数据库连接信息、数据库表对应实体类别名、类型处理器、插件、SQL 映射文件Mapper.xml 等信息。文件以 configuration
标签开头。标签如下所示(具体的配置(略)):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <configuration> <properties resource=""/>
<settings></settings>
<typeAliases></typeAliases>
<typeHandlers></typeHandlers>
<plugins></plugins>
<environments default="development"></environments>
<mappers></mappers> </configuration>
|
2、编写数据库表对应的实体类,将数据库表字段映射成Java类中的属性。
3、编写 Mapper 接口和对应的 Mapper.xml 文件,并在 Mapper 当中书写相应的 SQL 语句。以下是 Mapper 文件中的相关标签及其作用:
1 2 3 4 5 6 7 8 9 10 11
| <mapper namespace="org.apache.ibatis.domain.blog.mappers.AuthorMapper">
<parameterMap> </parameterMap>
<resultMap></resultMap>
<select id="selectAllAuthorsLinkedList" resultType="org.apache.ibatis.domain.blog.Author"> select * from author </select> </mapper>
|
配置文件的加载与解析流程
在日常开发中,我们也会发现在程序启动时会先将以上的配置文件先加载到内存并进行解析;可以通过 MyBatis 的一段单元测试来了解其中的流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private static SqlSessionFactory sqlSessionFactory;
@BeforeAll static void setUp() throws Exception { try ( Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/no_param_type/mybatis-config.xml")); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); }
BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), "org/apache/ibatis/submitted/no_param_type/CreateDB.sql"); }
|
经过调试,可以看出大致的流程如下:
将主配置文件加载进内存,生成字符流 –> 使用 XPath 对 XML 进行解析,转成可解析的 XMLConfigBuilder 对象 –> 将信息解析成Configuration对象,通过配置信息 Configuration 构建 SqlSessionFactory
对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse());
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"));
mapperElement(root.evalNode("mappers")); ...部分代码省略... }
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); configurationElement(parser.evalNode("/mapper")); configuration.addMapper(boundType);
|
总结:xml 文件配置信息经过加载,解析,最终会解析成 Configuration 对象以供程序后续的使用。