MyBatis中是如何对占位符进行赋值的?
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:
<select id="getUserById" resultType="User">
SELECT * FROM user WHERE id = #{id} AND name = #{name}
</select>
Mapper 接口:
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
User getUserById(@Param("id") int id, @Param("name") String name);
}
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
方法将参数值设置到占位符中。