MapperMethod中的SqlCommand和MethodSignature
一、SqlCommand的作用
职责:封装 SQL 命令的元信息。
关键属性:
name:Mapper 方法对应的 SQL 语句的唯一标识(通常是 命名空间.方法名,如 UserMapper.selectById)。
type:SQL 操作类型(SELECT, INSERT, UPDATE, DELETE, FLUSH等)。
来源:解析 Mapper 接口方法对应的 XML 或注解中的 SQL 定义。
二、MethodSignature的作用
职责:封装 Mapper 接口方法的签名信息。
关键属性:
returnType:方法返回类型(区分基本类型、集合、游标、Map 等)。
paramNameResolver:参数名解析器(处理 @Param注解、参数名映射)。
returnsVoid:方法是否返回 void。
returnsMany:是否返回集合(如 List)。
returnsMap:是否返回 Map。
returnsCursor:是否返回游标(Cursor)。
参数类型信息:用于动态 SQL 的参数绑定。
调用流程示例
假设有如下 Mapper 接口和 XML 配置
public interface UserMapper {User selectById(@Param("id") Long id, UserQuery query);
}
<!-- UserMapper.xml -->
<select id="selectById" resultType="User">SELECT * FROM user WHERE id = #{id} AND status = #{query.status}
</select>
步骤 1:初始化 MapperMethod
当首次调用 UserMapper.selectById()时,MyBatis 会创建 MapperMethod实例:
SqlCommand初始化:
name= "UserMapper.selectById"
type= SELECT(根据 XML 中的 <select>标签确定)
MethodSignature初始化:
returnType= User.class
paramNameResolver解析参数:
第一个参数 id被 @Param("id")注解 → 命名为 "id"
第二个参数 query无注解 → 命名为 "query"(或使用反射获取参数名)
步骤 2:方法调用触发执行
当调用 userMapper.selectById(100L, new UserQuery(“active”))时:
//内部会通过Invoke调用下面代码
MapperMethod.execute(sqlSession, args);
步骤 3:SqlCommand定位 SQL
通过 command.name找到对应的 SQL 语句(UserMapper.selectById)。
根据 command.type决定执行 sqlSession.select()/update()等方法。
步骤 4:MethodSignature处理参数
参数转换:
使用 paramNameResolver将方法参数转换为 SQL 参数 Map:
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("id", 100L); // @Param("id") 映射
paramMap.put("query", userQuery); // 参数名 "query" 映射参数绑定:
SQL 中的 #{id}→ 从 paramMap取 key="id"的值(100L)。
#{query.status}→ 从 paramMap取 key="query"的对象,再取其 status属性("active")。
步骤 5:执行 SQL 并处理结果
调用
sqlSession.selectOne(command.name, paramMap)。
结果处理:
根据 MethodSignature.returnType决定返回值类型(此处为 User)。
若返回集合(如 List<User>),会调用 selectList并自动包装为集合。