【JavaEE进阶】#{}和${}

[复制链接]
发表于 2025-10-28 18:37:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
🍃前言

MyBatis参数赋值有两种⽅式,使⽤ #{} 和 ${}进⾏赋值,接下来我们看下⼆者的区别
🌳#{}和${}使⽤

我们先来看一下两者在底子数据范例与string范例下的利用
🚩Interger范例的参数(底子数据范例)

🏀利用#{}

代码:

我们观察一下我们的打印日记:

发现我们输出的SQL语句:
select * from userinfo where id = ?
我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位.这种SQL我们称之为"预编译SQL"
🏀利用${}

代码:

观察一下我们的打印日记:

发现我们输出的SQL语句:
select * from userinfo where id = 2
可以看到,这次的参数是直接拼接在SQL语句中了.
🚩String范例的参数

🏀利用#{}

代码:

观察打印日记:

结果与上面一样乐成返回
🏀利用${}

代码:

再次举行打印日记:​​​​​​​

可以看到,这次的参数依然是直接拼接在SQL语句中了,但是字符串作为参数时,须要添加引号' ',使⽤ ${} 不会拼接引号' ',导致步调报错
修改代码如下:

再次运行

从上⾯两个还例⼦可以简单看出:
#{} 使⽤的是预编译SQL,通过 ? 占位的⽅式,提前对SQL进⾏编译,然后把参数添补到SQL语句中.
#{} 会根据参数范例,⾃动拼接引号' ',把他酿成字符串 .${} 会直接进⾏字符更换,⼀起对SQL进⾏编译.如果参数为字符串,须要加上引号 ’ ’
参数为数字范例时,也可以加上引号,查询结果稳固,但是大概会导致索引失效,性能降落
🎍#{}和${}区别

#{}和${}的区别就是预编译SQL和即时SQL的区别.
🚩#{}性能更高

绝⼤多数环境下,某⼀条SQL语句大概会被反复调⽤执⾏,大概每次执⾏的时间只有个别的值差异(⽐如select的where⼦句值同,update的set⼦句值差异,insert的values值差异).
如果每次都须要颠末上⾯的语法剖析,SQL优化、SQL编译等,则服从就显着不⾏了.
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译(只是输⼊的参数差异),省去相识析优化等过程,以此来提⾼服从
🚩#{}更安全(防止SQL注入)

$存在SQL注入的标题,我们知道,$符号是直接拼接的,那么我们在拼接的时间,就可以拼接一些别的信息,不愿定是传参
SQL注⼊:是通过操纵输⼊的数据来修改事先界说好的SQL语句,以到达执⾏代码对服务器进⾏攻击的⽅法
缘故起因:由于没有对⽤⼾输⼊进⾏充实查抄,⽽SQL⼜是拼接⽽成,在⽤⼾输⼊参数时,在参数中添加⼀些SQL关键字,到达改变SQL运⾏结果的⽬的,完成恶意攻击
接下来我们先看一个sql注入的例子:
注入sql代码: ' or 1='1
起首我们有以下代码:​​​​​​​

当我们正常传参数时,代码如下:​​​​​​​

正常运行结果如下:​​​​​​​

接下来我们注入sql代码如下:

再次运行:结果依然被准确查询出来了,此中参数or被当做了SQL语句的⼀部门

但是呢,我们须要查询的应该是一个人的信息,这里却将全部人的信息给打印了出来。
更早期会出现直接删数据,但是这种mybatis不支持
' '; delete from info; -- '
🚩${}的利用场景

从上⾯的例⼦中,可以得出结论 {}会有SQL注⼊的⻛险,以是我们只管使⽤#{}完成查询
既然云云,是不是$ { }就没有存在的须要性了呢?
固然不是.接下来我们看下${}的使⽤场景
🏀排序功能

接下来我们来实现通过通报参数让表实现降序排序:
我们先用#{}
代码:

当我们举行传参:

举行启动:

可以发现,当使⽤ #{order} 查询时,desc前后⾃动给加了引号,导致sql错误
利用${}就可以克制这种环境:

启动测试:

由于照旧参数通报,这种依然存在SQL注入标题,要想不存在SQL注入标题,就须要控制用户的入参,可以通过罗列的方式,只能为desc/asc
除了这个之外,另有表名作为参数时,也只能使⽤ ${}
🏀like查询

同样,like使⽤#{}报错

把#{}改成$ {}可以准确查出来,但是$ {}存在SQL注⼊的标题,以是不能直接使⽤${}

🍀#{}和${}区别总结


  • #{}:预编译处理处罚,${}:字符直接更换
  • #{}可以防⽌SQL注⼊,${}存在SQL注⼊的⻛险,查询语句中,可以使⽤#{},保举使⽤#{}
  • 但是⼀些场景,#{}不能完成,⽐如排序功能,表名,字段名作为参数时,这些环境须要使⽤${}
  • 暗昧查询固然${}可以完成,但由于存在SQL注⼊的标题,以是通常使⽤mysql内置函数concat来完成
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表