MyBatis 中对占位符进行赋值的过程主要由 PreparedStatement 和参数处理器 (ParameterHandler) 协同完成。
1. SQL 语句中的占位符:
MyBatis 支持两种占位符:
-
#(预编译参数): 推荐使用。- MyBatis 会使用
PreparedStatement的占位符?来处理。 PreparedStatement会对参数进行预编译和类型检查,可以防止 SQL 注入攻击。- 例如:
SELECT * FROM user WHERE id = #{id}
- MyBatis 会使用
-
$(字符串替换): 不推荐,除非有特殊需求。- MyBatis 会直接将参数值替换到 SQL 语句中。
- 存在 SQL 注入的风险。
- 例如:
SELECT * FROM user WHERE id = ${id}
2. 赋值流程 (以 # 占位符为例):
-
解析 SQL 语句:
- MyBatis 解析 Mapper XML 文件或注解中的 SQL 语句。
- 将 SQL 语句中的
#占位符替换为?。 - 例如,将
SELECT * FROM user WHERE id = #{id} AND name = #{name}转换为SELECT * FROM user WHERE id = ? AND name = ?。
-
创建
PreparedStatement:- MyBatis 使用 JDBC 的
Connection对象创建PreparedStatement对象。
- MyBatis 使用 JDBC 的
-
获取参数值:
- MyBatis 根据参数的名称或位置,从以下来源获取参数值:
- 单个参数: 如果只有一个参数,可以直接传入。
- 多个参数:
- 使用
@Param注解: 可以通过@Param注解为参数指定名称。 - 使用 Map: 可以将参数放入
Map中,键为参数名称,值为参数值。 - 使用 JavaBean: 可以将参数封装到 JavaBean 中,属性名与参数名称对应。
- 按参数顺序 如果没有
@Param注解, 也没有使用Map, 则按照参数定义的顺序.
- 使用
- 如果是基本类型包装类, 会自动进行拆箱.
- MyBatis 会根据配置的类型处理器 (
TypeHandler),将 Java 对象转换为 JDBC 类型。
- MyBatis 根据参数的名称或位置,从以下来源获取参数值:
-
设置参数值:
- MyBatis 使用
PreparedStatement的setXXX方法(如setInt、setString、setDouble等),根据参数的类型和位置,将参数值设置到PreparedStatement的占位符中。 - 会根据配置的
TypeHandler将 Java 类型转换为 JDBC 类型。
- MyBatis 使用
-
执行 SQL 语句:
- MyBatis 执行
PreparedStatement的executeQuery、executeUpdate或execute方法,执行 SQL 语句。
- MyBatis 执行
示例:
Mapper XML:
xml
<select id="getUserById" resultType="User">
SELECT * FROM user WHERE id = #{id} AND name = #{name}
</select>
Mapper 接口:
java
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
User getUserById(@Param("id") int id, @Param("name") String name);
}
Java 代码:
java
// ... 获取 SqlSession
User user = sqlSession.getMapper(UserMapper.class).getUserById(1, "John");
执行流程:
- MyBatis 解析
getUserById方法的 SQL 语句,将#占位符替换为?,得到SELECT * FROM user WHERE id = ? AND name = ?。 - MyBatis 创建
PreparedStatement对象。 - MyBatis 从方法参数中获取
id(值为 1) 和name(值为 "John")。 - MyBatis 使用
PreparedStatement的setInt(1, 1)和setString(2, "John")方法,将参数值设置到占位符中。 - MyBatis 执行
PreparedStatement的executeQuery方法,执行 SQL 语句,并将结果映射为User对象。
ParameterHandler:
ParameterHandler是 MyBatis 中负责处理参数设置的接口。- 默认实现类是
DefaultParameterHandler。 DefaultParameterHandler会根据参数的类型和配置的TypeHandler,选择合适的PreparedStatement.setXXX方法来设置参数值。
TypeHandler:
TypeHandler是 MyBatis 中负责 Java 类型和 JDBC 类型之间转换的接口。- MyBatis 内置了许多
TypeHandler,用于处理常见的类型转换。 - 可以自定义
TypeHandler来处理特殊的类型转换。
总结:
MyBatis 通过 PreparedStatement 和参数处理器 (ParameterHandler) 来实现对占位符的赋值。 它支持 #(预编译参数)和 $(字符串替换)两种占位符,推荐使用 # 占位符,以防止 SQL 注入攻击。 MyBatis 会根据参数的类型和配置的 TypeHandler,将 Java 对象转换为 JDBC 类型,并使用 PreparedStatement 的 setXXX 方法将参数值设置到占位符中。