Mybatis中#{}和${}的区别是什么

在MyBatis中,#{}${}是两种参数替换方式,核心区别在于安全性预编译处理使用场景。以下是详细对比:


1. 核心区别

特性​**#{}**​**${}**
处理方式预编译(PreparedStatement),参数替换为占位符?字符串直接替换(字符串拼接)
安全性✅ 防止SQL注入❌ 存在SQL注入风险
适用场景参数值替换(如WHERE条件、INSERT值)动态SQL片段(如表名、列名、排序字段)
引号处理自动根据类型添加引号(如字符串加''直接替换,需手动处理引号(如'${value}'

2. 使用示例

​**(1) 查询用户(安全场景)​**
 

xml

<!-- 使用#{},生成预编译SQL -->
<select id="getUser" resultType="User">
    SELECT * FROM user WHERE name = #{name}
</select>

生成的SQL

 

sql

SELECT * FROM user WHERE name = ?  -- 参数值被预编译处理
​**(2) 动态表名(必须用${})​**
 

xml

<!-- 使用${}直接替换表名 -->
<select id="getLogs" resultType="Log">
    SELECT * FROM ${tableName} WHERE type = #{type}
</select>

参数tableName = "sys_log_2023", type = "error"
生成的SQL

 

sql

SELECT * FROM sys_log_2023 WHERE type = 'error'  -- 表名直接拼接
​**(3) SQL注入风险示例**
 

xml

<!-- 恶意输入导致SQL注入 -->
<select id="getUser" resultType="User">
    SELECT * FROM user WHERE name = '${name}'
</select>

参数name = "admin' OR '1'='1"
生成的SQL

 

sql

SELECT * FROM user WHERE name = 'admin' OR '1'='1'  -- 返回所有用户数据

3. 最佳实践

  • 优先使用#{}
    适用于所有参数值替换(如WHERE条件、INSERT/UPDATE的字段值)。

     

    xml

    INSERT INTO user (name, age) VALUES (#{name}, #{age})
  • 谨慎使用${}
    仅在动态SQL片段(如表名、列名、排序字段)时使用,并严格校验参数来源。

     

    xml

    ORDER BY ${sortField} ${sortOrder}  -- 确保sortField和sortOrder值合法
  • 模糊查询的正确写法
    使用CONCAT函数结合#{},而非直接拼接%

     

    xml

    SELECT * FROM user WHERE name LIKE CONCAT('%', #{keyword}, '%')

4. 底层原理

机制​**#{}**​**${}**
替换阶段在SQL预编译阶段替换为?,由JDBC驱动处理类型在SQL解析阶段直接替换为字符串
数据库优化预编译SQL可被缓存,提升执行效率每次生成新SQL,需重新解析
特殊字符转义自动转义(如单引号' → ''直接替换,需手动转义(如'${value}'

5. 常见问题

​**(1) 何时必须用${}?**
  • 动态表名/列名:
     

    xml

    SELECT * FROM ${tableName} WHERE ${column} = #{value}
  • SQL关键字(如排序方式):
     

    xml

    ORDER BY create_time ${order}
​**(2) 如何防止${}的SQL注入?**
  • 白名单校验:检查参数值是否在允许的范围内(如预定义的列名、表名)。
  • 避免用户输入:动态SQL片段应由系统生成,而非直接接受用户输入。

总结

  • ​**#{}**:安全、预编译、自动类型处理,适用于参数值替换。
  • ​**${}**:灵活但危险,直接字符串替换,适用于动态SQL片段。
  • 核心原则:能用#{}则不用${},必须用${}时需严格校验参数合法性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值