mybatis 中 #{} 和 ${} 核心区别在于处理方式和安全性。#{} 是预编译占位符,安全;${} 是字符串拼接,有注入风险 。
怎么防止 sql 注入
-
#{}:底层使用 jdbc 的preparedstatement,参数作为占位符?传入,数据库会自动转义特殊字符,有效防止 sql 注入 。 -
${}:直接将参数值拼接到 sql 字符串中,若参数包含' or '1'='1等恶意代码,会改变 sql 逻辑,导致数据泄露 。
什么时候用哪个
- 优先用
#{}:绝大多数场景,如where条件、insert值、update值等参数传递,直接使用#{}即可 。 - 慎用
${}:仅在需要动态替换 sql 结构时使用,例如动态表名、列名、排序关键字(order by),且需确保参数来源可信或经过白名单校验 。
性能有什么差别
-
#{}:预编译 sql 可缓存执行计划,重复执行时性能略高,且类型转换自动处理 。 -
${}:每次执行都需要重新拼接和编译 sql,性能略低,且字符串类型参数需手动添加单引号,否则会报错 。
在这篇博客中,我们将详细探讨 mybatis 框架中使用的两种参数替换机制:# 和 $ 的标记。了解这两种方式的区别非常重要,因为它们在安全性和功能上有明显的不同。我们将通过示例来说明这些差异,并提供实用的建议,以帮助开发者选择适当的方式,以确保应用程序的安全性和效率。
参数替换的基本概念
在 mybatis 中,# 和 $ 用于在 sql 语句中插入参数。它们虽然都能将参数传递到 sql 语句中,但处理方式和结果却大不相同。
#参数的特点
- 安全性:使用
#标记的参数在 sql 语句中被当做字符串处理。mybatis 会自动为这些参数加上引号,这意味着传入的参数被安全地视为字面量。 - 防sql注入:
#的自动引号功能极大地增强了防止 sql 注入的能力。由于参数不会被解释为 sql 代码的一部分,恶意输入也无法改变 sql 语句的结构。
示例:
select id, name, age from student where id = #{id}当传递参数 id 为 “1” 时,sql 解析为:
select id, name, age from student where id = "1"
$参数的特点
- 直接替换:使用
$标记的参数会被直接替换到 sql 语句中,而不会添加任何引号,这使得参数可以被解释为 sql 语句的一部分。 - 风险:由于
$的这种直接替换特性,它无法防止 sql 注入。如果参数包含恶意 sql 代码,可能会导致安全漏洞。
示例:
select id, name, age from student where id = ${id}当传递参数 id 为 “1” 时,sql 解析为:
select id, name, age from student where id = 1
使用场景比较
#的使用场景
在大多数情况下,推荐使用 # 来传递参数。它适用于几乎所有的标准 sql 操作,能有效防止 sql 注入,是一种安全的选择。
$的使用场景
虽然风险较高,但 $ 在某些情况下仍然是必需的,特别是当需要动态传入数据库对象名(如表名、列名)或进行复杂的 sql 构造(如动态排序)时。
例子:
select id, name, age from ${tablename} order by ${columnname}结论
理解并正确使用 # 和 $ 是保障 mybatis 应用安全与效率的关键。开发者应优先选择 # 来避免 sql 注入的风险。对于需要使用 $ 的特定场景,务必确保传入参数的来源是可控且安全的。
到此这篇关于mybatis中#和$的区别对比分析(通俗简单易解版)的文章就介绍到这了,更多相关mybatis中#和$的区别内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论