栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java开发MySQL中#{} 和 ${}的区别

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java开发MySQL中#{} 和 ${}的区别

梗概

#{}: 占位符号,可以防止sql注入,自己会带有双引号;

${}:sql拼接符号,存在sql注入问题,需要在代码中过滤以避免注入,不会带有双引号;

MyBatis排序使用order by 动态参数时,用${}而不是#{}。

详细区别

#{}:

SELECt * FROM user WHERe name = #{nameParam};

解析为一个JDBC预编译语句后:

SELECt * FROM user WHERe name = ?;

即#{} 解析为?,当 nameParam = "Bob" 时:

SELECt * FROM user WHERe name = "Bob"; //带有引号

${}:

SELECt * FROM ${tableNameParam};

${}是一个纯粹的string替换,动态解析时,会进行变量替换,不带有引号,当tableNameParam= "user" 时:

SELECt * FROM user

即预编译之前SQL中就已经不包含变量,而是被替换成常量数据了

[ sql预编译]  sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。


详细部分小结

#{}变量的替换是在DBMS中,而${}变量的替换是在动态SQL解析阶段


使用小诀窍

优先使用#{},即能用#{}就用#{}:

1、从性能方面考虑,相同的预编译sql可以重复利用

2、${}在预编译之前就已经被替换为常量,会存在sql注入问题


表名作为变量时,必须用${}:

SELECt * FROM #{tableNameParam}

预编译完成后,sql变为:

SELECt * FROM ?

当参数tableNameParam = "user" 时,sql变为

SELECt * FROM 'user'

这会导致 sql 语法错误,表名不能加单引号 ''(反引号 ``是可以的)。


当用${}时:

SELECt * FROM ${tableNameParam}

同样当参数tableNameParam = "user" 时,sql变为:

SELECt * FROM user

同样的道理,ORDER BY排序时,也只能用${}


sql注入:

SELECt * FROM ${tableNameParam} WHERe name = #{nameParam};

假设上如sql语句,tableNameParam = user; delete user; -- 还有 nameParam = Bob,那么编译前:

SELECT * FROM user; delete user; -- WHERe name = ?;

动态编译完成后:

SELECT * FROM user; delete user; -- WHERe name = "Bob";

那么实际执行的sql一共两句:

SELECT * FROM user;
delete user;

而 -- 之后的语句会被作为注释,不起作用;这时本来的一条查询语句,被注入了一个删除表数据的SQL。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/489342.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号