1. MyBatis双模式工作原理深度拆解
MyBatis作为Java生态中最受欢迎的ORM框架之一,其核心价值在于提供了SQL与Java对象之间的优雅映射方案。在实际开发中,我们主要通过XML映射文件和注解两种方式实现这种映射关系。理解这两种模式的底层机制,是高效使用MyBatis的关键。
1.1 XML映射文件的解析过程
当MyBatis启动时,会通过XMLConfigBuilder解析主配置文件,遇到<mapper>标签时,会触发XMLMapperBuilder对指定路径下的Mapper XML文件进行解析。这个过程中有几个关键节点值得关注:
-
命名空间绑定:每个Mapper XML的namespace属性必须与对应的Mapper接口全限定名一致。MyBatis通过
MapperRegistry维护这个绑定关系,这是接口方法与SQL语句关联的基础。 -
SQL节点处理:对于
<select>、<insert>等SQL节点,MyBatis会创建MappedStatement对象,其中包含SQL源码、参数映射、结果映射等核心元数据。特别值得注意的是,动态SQL标签(如<if>、<foreach>)会在此时被解析为SqlNode构成的抽象语法树。 -
参数映射构建:
<parameterMap>和参数类型推断共同决定了Java方法参数如何转换为SQL参数。MyBatis会创建ParameterMapping对象记录每个参数的名称、类型、处理器等信息。 -
结果集映射:
<resultMap>定义了数据库列到Java属性的映射规则。MyBatis会构建ResultMap对象,其中包含多个ResultMapping实例,处理包括简单类型转换、嵌套结果映射、关联查询等复杂场景。
xml复制<!-- 典型Mapper XML示例 -->
<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="user_name"/>
<collection property="roles" ofType="Role" select="selectRolesByUserId"/>
</resultMap>
<select id="selectUser" resultMap="userResultMap">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
1.2 注解模式的实现机制
注解模式通过Java接口上的元数据实现SQL映射,其核心处理类MapperAnnotationBuilder的工作流程如下:
-
方法签名解析:解析接口方法时,MyBatis会检查参数列表和返回类型。例如,
@Param注解会影响参数绑定方式,而返回类型决定结果处理策略(单个对象、集合、Map等)。 -
SQL注解处理:
@Select、@Insert等注解携带的SQL语句会被提取并解析。与XML不同,注解中的SQL是直接以字符串形式嵌入代码的,这带来了更好的IDE支持但牺牲了部分可读性。 -
动态SQL支持:通过
@SelectProvider等注解可以指定SQL提供类,这类类需要实现ProviderMethodResolver接口,返回动态生成的SQL字符串。这是注解模式下实现复杂动态SQL的主要方式。
java复制public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
@Results({
@Result(property = "id", column = "user_id"),
@Result(property = "roles", column = "id",
many = @Many(select = "selectRol
