14. /#{} 和 /${} 的区别是什么?

在MyBatis中,#{}${}是两种常见的占位符,它们的作用和使用场景有所不同。理解它们的区别对于正确使用MyBatis非常重要。

1. #{} 和 ${} 的基本区别

#{}:SQL参数占位符

  • 作用#{}用于将传入的参数安全地绑定到SQL语句中,它会自动使用PreparedStatement?占位符机制,并且MyBatis会对传入的参数进行预处理(例如防止SQL注入)。

  • 参数替换 :在生成SQL语句时,#{}会被替换为一个?,然后由JDBC驱动程序将参数值绑定到这个?占位符上。

  • 使用场景:通常用于传递用户输入的参数,如查询条件、插入或更新的数据等。

    示例

    java 复制代码
    <select id="findUserById" resultType="User">
        SELECT * FROM users WHERE id = #{id}
    </select>
    • 如果传入的id为1,MyBatis生成的SQL类似于:SELECT * FROM users WHERE id = ?,然后通过PreparedStatement?替换为1。

${}:SQL文本占位符

  • 作用${}用于直接将传入的参数值替换到SQL语句中,它不会进行预处理,因此直接将参数值插入到SQL语句中。这意味着${}会将参数视为SQL的一部分,可能会导致SQL注入风险。

  • 参数替换 :在生成SQL语句时,${}会直接将传入的值替换到SQL语句中,而不会使用?占位符。

  • 使用场景:通常用于动态生成SQL片段,比如排序字段名、表名、列名等不直接来自用户输入的参数。

    示例

    java 复制代码
    <select id="findUserByColumn" resultType="User">
        SELECT * FROM users WHERE ${columnName} = #{value}
    </select>
    • 如果传入的columnNameusernamevalueJohn,MyBatis生成的SQL类似于:SELECT * FROM users WHERE username = ?,然后通过PreparedStatement?替换为John

2. 安全性和使用建议

  • SQL注入防护 :由于#{}会使用PreparedStatement的参数绑定机制,因此可以有效防止SQL注入攻击。而${}直接将参数值拼接到SQL中,可能导致SQL注入,因此应慎重使用。

  • 动态SQL生成${}更适合用于生成动态的SQL片段,比如动态表名、列名等。但要确保传入的值是可信任的,或者通过其他手段确保安全。

3. 具体示例

使用 #{} 的示例

java 复制代码
<select id="findUserById" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>
  • 传入id为1,生成SQL为:

    java 复制代码
    SELECT * FROM users WHERE id = ?

    然后将参数1安全地绑定到?上。

使用 ${} 的示例

java 复制代码
<select id="findUserByColumn" resultType="User">
    SELECT * FROM users WHERE ${columnName} = #{value}
</select>
  • 传入columnNameusernamevalueJohn,生成SQL为:

    java 复制代码
    SELECT * FROM users WHERE username = ?

    然后将参数John绑定到?上。

SQL注入风险示例

java 复制代码
<select id="findUserByColumn" resultType="User">
    SELECT * FROM users WHERE ${columnName} = #{value}
</select>
  • 如果传入的columnNameusername OR '1'='1',生成的SQL可能是:

    java 复制代码
    SELECT * FROM users WHERE username OR '1'='1' = ?

    这样就可能导致SQL注入问题。

总结

  • #{}:安全地传递参数,防止SQL注入,常用于传递用户输入的参数。

  • ${}:直接将参数值插入到SQL中,适用于动态生成SQL片段(如表名、列名),但存在SQL注入风险,应谨慎使用。

在实际开发中,建议尽量使用#{}来传递参数,以确保SQL安全性,而对于使用${}的场景,需要确保传入的参数是安全且经过验证的。

相关推荐
没有梦想的咸鱼185-1037-16637 分钟前
基于R语言机器学习方法在生态经济学领域中的实践技术应用
开发语言·机器学习·数据分析·r语言
a587699 分钟前
消息队列(MQ)初级入门:详解RabbitMQ与Kafka
java·分布式·microsoft·面试·kafka·rabbitmq
千里码aicood20 分钟前
【springboot+vue】党员党建活动管理平台(源码+文档+调试+基础修改+答疑)
java·数据库·spring boot
Chan1624 分钟前
【智能协同云图库】基于统一接口架构构建多维度分析功能、结合 ECharts 可视化与权限校验实现用户 / 管理员图库统计、通过 SQL 优化与流式处理提升数据
java·spring boot·后端·sql·spring·intellij-idea·echarts
先做个垃圾出来………30 分钟前
差分数组(Difference Array)
java·数据结构·算法
向上的车轮31 分钟前
基于go语言的云原生TodoList Demo 项目,验证云原生核心特性
开发语言·云原生·golang
The Chosen One98532 分钟前
C++ : AVL树-详解
开发语言·c++
PH_modest43 分钟前
【Qt跬步积累】—— 初识Qt
开发语言·qt
BillKu1 小时前
Java核心概念详解:JVM、JRE、JDK、Java SE、Java EE (Jakarta EE)
java·jvm·jdk·java ee·jre·java se·jakarta ee
怀旧,1 小时前
【C++】18. 红⿊树实现
开发语言·c++