# 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. 字符串替换
使用${}占位符可以在SQL语句中实现字符串的替换功能。在SQL被执行之前,MyBatis会简单地将${expression}替换为对应的值,不关心值的类型。

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

### 4. SQL注入风险
由于${}的替换是简单的字符串连接,没有对参数值进行任何处理,所以使用${}可能存在SQL注入的风险。如果参数值是用户输入的内容,需要进行严格的校验和过滤,以避免潜在的安全问题。

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

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

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

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

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