MyBatis 是一个简单、灵活的持久层框架,它通过 SQL 语句将 Java 对象与数据库进行映射。MyBatis 支持基于 XML 和注解的配置方式。在实际开发中,XML 映射文件与 Mapper 接口的关联是 MyBatis 的核心功能之一。通过这种关联,开发者可以在 Mapper 接口中定义方法,并在 XML 文件中编写 SQL 语句,从而实现数据操作。
首先,我们需要了解 Mapper 接口和 XML 映射文件的基础结构:
public interface UserMapper {
User selectUserById(int id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUserById" parameterType="int" resultType="com.example.model.User">
SELECT * FROM users WHERE id = #{id}
select>
mapper>
Mapper 接口和 XML 映射文件通过以下方式关联:
namespace
:XML 映射文件中的 namespace
属性值必须与 Mapper 接口的全限定名一致,即 com.example.mapper.UserMapper
。id
:XML 文件中 SQL 语句的 id
值要与接口中的方法名保持一致,如 selectUserById
。这样,MyBatis 就能根据接口中的方法名找到对应的 SQL 语句并执行。
MyBatis 内部是如何将 Mapper 接口与 XML 文件关联起来的?接下来深入讲解具体的流程。
MyBatis 使用动态代理模式为每个 Mapper 接口创建代理对象。当你调用 UserMapper
中的方法时,实际上调用的是 MyBatis 生成的代理对象。这个代理对象会根据方法名查找与之关联的 SQL 语句,并将参数传入到 SQL 中执行,最后返回结果。
代码示例:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectUserById(1);
sqlSession.getMapper(UserMapper.class)
会通过 MyBatis 的代理工厂为 UserMapper
创建一个代理对象。当调用 selectUserById(1)
时,代理对象会根据接口的方法名查找相应的 SQL 语句。
MapperRegistry
和 MapperProxyFactory
在 MyBatis 内部,MapperRegistry
是负责管理和维护 Mapper 接口与其代理工厂的核心类。它会将所有的 Mapper 接口注册进来并生成相应的代理对象。
MapperProxyFactory
是为每个 Mapper 接口创建代理对象的工厂类。它利用 java.lang.reflect.Proxy
来动态生成代理对象,并通过 MapperProxy
处理具体的 SQL 调用。
关联过程:
MapperRegistry
注册 Mapper 接口。getMapper
方法时,MapperProxyFactory
生成相应的代理对象。MapperProxy
调用对应的 SQL 语句。在 MyBatis 启动时,所有的 Mapper 映射文件会被解析并加载到 Configuration
对象中。Configuration
是 MyBatis 的核心配置类,它包含了所有与 Mapper 相关的配置信息,包括 SQL 映射、缓存、拦截器等。
MyBatis 解析 XML 映射文件时,主要通过以下几步:
namespace
,与对应的 Mapper 接口进行匹配。id
属性,将其与接口中的方法进行对应。MyBatis 使用 XMLMapperBuilder
类解析 XML 文件。它通过解析 XML 节点,生成对应的 MappedStatement
对象,每个 MappedStatement
对象代表一个 SQL 语句与方法的映射关系。
解析过程:
mapper
文件。XMLMapperBuilder
类解析 XML 文件,读取 namespace
和 id
。MappedStatement
对象。MappedStatement
被存储在 Configuration
对象的 mappedStatements
集合中。假设我们有以下配置:
Mapper 接口:
public interface OrderMapper {
Order selectOrderById(int id);
}
XML 映射文件:
<mapper namespace="com.example.mapper.OrderMapper">
<select id="selectOrderById" parameterType="int" resultType="com.example.model.Order">
SELECT * FROM orders WHERE id = #{id}
select>
mapper>
核心关联流程:
SqlSessionFactoryBuilder
加载配置文件 mybatis-config.xml
,并根据配置文件路径加载 OrderMapper.xml
。XMLMapperBuilder
解析 XML 文件,读取 namespace
和 id
。MappedStatement
:将 selectOrderById
方法与对应的 SQL 语句绑定,生成 MappedStatement
对象并存储在 Configuration
中。sqlSession.getMapper(OrderMapper.class)
调用时,MyBatis 通过 MapperProxyFactory
为 OrderMapper
创建代理对象。selectOrderById
方法时,代理对象会根据方法名查找 MappedStatement
,并执行对应的 SQL 语句,最终将结果返回。MyBatis 不仅支持静态 SQL,还支持动态 SQL,可以根据条件动态生成 SQL 语句。在 XML 文件中,可以使用
、
、
等标签来构建灵活的 SQL 语句。
动态 SQL 示例:
<select id="selectOrders" resultType="com.example.model.Order">
SELECT * FROM orders
WHERE 1=1
<if test="status != null">
AND status = #{status}
if>
<if test="customerId != null">
AND customer_id = #{customerId}
if>
select>
这种方式让 MyBatis 能够根据传入的参数动态拼接 SQL,提升了灵活性。
MyBatis 中 Mapper 接口与 XML 文件的关联过程,主要通过 namespace
和 id
来匹配。在内部,MyBatis 通过代理模式为 Mapper 接口生成代理对象,通过 MappedStatement
实现 SQL 语句与方法的绑定。这个过程使得开发者只需专注于业务逻辑,而不必过多关注底层的 SQL 细节。
整理不易,如果对你有帮助,那就点个免费的赞吧