# MyBatis 占位符 #{} 和 ${} 的用法和区别

## #{} 和 {} 的介绍  在 MyBatis 中,我们可以使用 #{} 和{} 来作为占位符,用于传递变量值给 SQL 语句中的参数或者替换变量值。这两种占位符的使用方法和区别如下所述。

## #{} 的用法和特点
### 1. #{parameterName} 的语法
在 SQL 语句中,我们可以使用 #{parameterName} 来表示一个参数,并且 parameterName 必须和方法参数的名称一致。在 SQL 被执行之前,MyBatis 会将参数的值进行预处理,并将其安全地传递给数据库。

### 2. 预编译
使用 #{} 占位符在 SQL 中,可以有效防止 SQL 注入攻击,因为 MyBatis 会预编译 SQL 语句,并使用 JDBC 的 PreparedStatement 来绑定参数值。

### 3. 参数值的类型安全检查
在使用 #{} 占位符时,MyBatis 会根据参数的类型自动匹配相应的 JDBC 类型,从而确保参数值的类型安全。此外,MyBatis 还可以通过类型处理器 (TypeHandler) 来处理一些复杂的类型转换。

### 4. 防止 SQL 注入
由于 #{} 的预编译特性,它可以有效地防止 SQL 注入攻击。因为 #{} 会对参数值进行安全的处理,不会将用户输入的内容作为 SQL 语句的一部分。

## {} 的用法和特点  ### 1.{expression} 的语法
在 SQL 语句中,我们可以使用 ${expression} 来表示一个表达式,并且 expression 可以是一个变量名、一个对象的属性名,或者一个方法调用。

### 2. 字符串替换
使用 SQLSQLMyBatis{expression} 替换为对应的值,不关心值的类型。

### 3. 动态 SQL
使用 ${} 占位符时,字符串拼接是在 SQL 执行前完成的,因此它可以在 SQL 中实现动态表名、列名等。但是,这种方式会使代码容易受到 SQL 注入攻击。

### 4. SQL 注入风险
由于 使{} 可能存在 SQL 注入的风险。如果参数值是用户输入的内容,需要进行严格的校验和过滤,以避免潜在的安全问题。

## #{} 和 {} 的区别  根据上述介绍,我们可以总结出 #{} 和{} 的主要区别:

### 1. 预编译
#{} 占位符是 MyBatis 进行预编译的一部分,能够防止 SQL 注入,保证参数值的类型安全。而 ${} 占位符是只对字符串进行简单的替换,并不能进行预编译,存在 SQL 注入的风险。

### 2. 动态性
#{} 占位符在 SQL 执行时进行参数值的处理,具有较强的动态性,可以根据参数的类型自动匹配 JDBC 类型,而 ${} 占位符在 SQL 执行前进行字符串的替换,更适合用于动态表名、列名等的拼接。

### 3. 安全性
由于 #{} 占位符进行预编译,可以有效避免 SQL 注入攻击,保证应用的安全性。而 ${} 占位符存在 SQL 注入的风险,需要谨慎使用和进行参数校验。

总的来说,#{} 占位符安全性更高,适用于大部分的 SQL 语句,而 ${} 占位符更灵活,适用于一些动态拼接的 SQL 语句,但需要注意 SQL 注入的风险。在实际开发中,根据具体的需求和场景,选择合适的占位符使用方式。