Quantcast
Channel: 小蓝博客
Viewing all articles
Browse latest Browse all 3145

MyBatis源码分析:Mapper文件加载与解析过程

$
0
0

MyBatis源码分析:Mapper文件加载与解析过程

MyBatis 是一个流行的持久层框架,提供了简洁易用的 SQL 映射功能。在 MyBatis 中,Mapper文件负责将 SQL 语句与 Java 对象进行映射。了解 MyBatis 是如何加载和解析 Mapper 文件,对掌握 MyBatis 的运行原理至关重要。

下面我们从Mapper文件加载与解析的过程入手,逐步分析 MyBatis 在内部是如何实现这些功能的。

一、Mapper 文件的加载过程

1.1 Mapper 加载的时机

在 MyBatis 中,Mapper 文件的加载通常发生在应用启动时,伴随 MyBatis SqlSessionFactory 的初始化过程。SqlSessionFactory 是 MyBatis 中用于创建 SqlSession 实例的工厂,所有对数据库的操作都依赖于 SqlSession

Mapper 文件的加载与解析发生在 SqlSessionFactory 的初始化过程中,具体步骤如下:

  1. 配置文件加载(包括全局配置和数据源配置)。
  2. 注册 Mapper 文件或接口。
  3. 解析 Mapper XML 文件并构建 Mapper 对象。

1.2 核心加载类:Configuration

Configuration 是 MyBatis 的核心配置类,存储了全局的配置、Mapper 信息、SQL 语句等。Mapper 文件的加载主要通过 Configuration 类中的方法实现。

1.3 Mapper 加载的入口:XMLMapperBuilder

在 MyBatis 中,XMLMapperBuilder 类负责解析 Mapper XML 文件。Mapper 文件中的每一个 SQL 语句都会被解析,并映射到 Configuration 中对应的 MappedStatement 中。

加载 Mapper 文件的过程:
  1. MyBatis 在启动时,会通过 XMLConfigBuilder 解析全局配置文件(通常是 mybatis-config.xml)。
  2. XMLConfigBuilder 发现需要加载的 Mapper 文件时,会调用 MapperRegistry 注册 Mapper。
  3. MapperRegistry 会根据 Mapper 的配置,使用 XMLMapperBuilder 来解析并加载 Mapper 文件。

下面是核心代码的简化流程:

// 在 Configuration 类中注册 Mapper
public <T> void addMapper(Class<T> type) {
    mapperRegistry.addMapper(type);
}

// MapperRegistry 中的 addMapper 方法
public <T> void addMapper(Class<T> type) {
    // 检查 Mapper 是否已经注册
    if (hasMapper(type)) {
        return;
    }
    // 解析 XML 文件
    XMLMapperBuilder parser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
    parser.parse();
}
  • addMapper():将指定的 Mapper 类注册到 MapperRegistry 中。
  • XMLMapperBuilder:负责解析 Mapper 文件,并将其内容存储到 Configuration 中。

二、Mapper 文件的解析过程

2.1 XMLMapperBuilder 类

XMLMapperBuilder 是 MyBatis 用于解析 Mapper 文件的核心类。该类继承自 BaseBuilder,解析的过程主要包括以下几个方面:

  1. 读取并解析 mapper.xml 文件。
  2. 提取 SQL 语句(如 selectinsertupdatedelete)。
  3. 将解析后的 SQL 语句映射到 Configuration 中。
// XMLMapperBuilder 的 parse 方法
public void parse() {
    if (!configuration.isResourceLoaded(resource)) {
        // 解析 <mapper> 节点
        configurationElement(parser.evalNode("/mapper"));
        configuration.addLoadedResource(resource);
        bindMapperForNamespace();
    }
}
  • configurationElement():负责解析 <mapper> 节点,并处理其中的 SQL 语句。
  • bindMapperForNamespace():将 Mapper 的命名空间与对应的 Mapper 接口进行绑定。

2.2 Mapper 文件结构解析

Mapper XML 文件一般包含以下几个主要部分:

  1. <mapper>:根节点,包含命名空间(namespace)。
  2. <select><insert><update><delete>:定义 SQL 语句。
  3. <resultMap>:用于定义 SQL 结果集与 Java 对象的映射关系。
  4. <sql>:用于定义可复用的 SQL 片段。

以下是典型的 mapper.xml 文件结构:

<mapper namespace="com.example.UserMapper">
    <select id="selectUser" resultType="com.example.User">
        SELECT * FROM users WHERE id = #{id}
    </select>
  
    <insert id="insertUser" parameterType="com.example.User">
        INSERT INTO users (name, email) VALUES (#{name}, #{email})
    </insert>
</mapper>
  • namespace:用于绑定 Mapper 接口和 XML 文件。
  • id:SQL 语句的唯一标识符,用于在调用 SQL 时通过 id 进行调用。

2.3 SQL 语句的解析

XMLMapperBuilder 解析 SQL 语句的具体过程主要依赖于 XMLStatementBuilder。该类负责解析 SQL 语句(如 <select><insert> 等),并将这些语句封装到 MappedStatement 中。

// XMLStatementBuilder 中解析 SQL 语句的方法
public void parseStatementNode() {
    String id = context.getStringAttribute("id");
    String sqlCommandType = context.getName();
  
    // 创建 MappedStatement
    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType);
  
    // 设置 SQL 参数、结果类型等
    statementBuilder.parameterMap(parameterMap);
    statementBuilder.resultMaps(resultMaps);
  
    // 将解析后的 MappedStatement 注册到 Configuration 中
    configuration.addMappedStatement(statementBuilder.build());
}
  • MappedStatement:MyBatis 用于存储每个 SQL 语句的映射关系,包括 SQL 语句本身、参数类型、结果类型等。
  • sqlCommandType:SQL 语句的类型(SELECTINSERT 等)。

三、Mapper 与 Mapper 接口的绑定

在 MyBatis 中,Mapper 接口与 Mapper 文件通过命名空间进行绑定。命名空间是 XML 文件中的 namespace 属性,它的值必须与 Mapper 接口的全限定类名一致。

<mapper namespace="com.example.UserMapper">
    <!-- SQL 语句定义 -->
</mapper>

当 MyBatis 解析完 mapper.xml 文件后,会通过 MapperRegistry 将解析的 SQL 语句与 UserMapper 接口中的方法进行绑定。调用接口方法时,MyBatis 会根据方法名称和参数自动找到对应的 SQL 语句并执行。

四、重要的类和方法总结

类名作用
ConfigurationMyBatis 核心配置类,存储全局配置、已解析的 Mapper 文件和 SQL 映射信息。
MapperRegistry用于管理和注册 Mapper 接口与其对应的 Mapper 文件。
XMLMapperBuilder用于解析 mapper.xml 文件,并将解析结果存储到 Configuration 中。
MappedStatement表示 SQL 语句的映射,包含 SQL 语句的定义、参数类型、返回类型等信息。
XMLStatementBuilder负责解析具体的 SQL 语句(如 <select><insert>),并创建对应的 MappedStatement 对象。

五、总结

MyBatis 的 Mapper 文件加载与解析过程通过一系列核心类和方法实现:

  1. SqlSessionFactory 初始化时,通过 Configuration 类来管理并加载 Mapper 文件。
  2. XMLMapperBuilder 类负责解析 mapper.xml 文件中的 SQL 语句、resultMap 等。
  3. 解析后的 SQL 语句和映射关系被存储到 Configuration 中,通过 MappedStatement 进行管理。
  4. MyBatis 通过 MapperRegistry 将 Mapper 接口与 Mapper XML 文件中的 SQL 语句绑定,保证应用程序中的 SQL 调用能够正确执行。

通过深入了解 MyBatis Mapper 文件的加载与解析机制,开发者可以更好地掌握 MyBatis 的运行原理,从而在实际项目中灵活运用,提升系统的可维护性与扩展性。


Viewing all articles
Browse latest Browse all 3145

Trending Articles