Mybatis 中 $ 和 #千万不要乱用

开头

这是一次代码优化过程中发现的问题,在功能优化后发现部分数据查不到出来了,问题就在于一条 sql 上的 #和 $。

下图为两条 sql:

从图上可以看出 wwlr.LabelId in(${showLabels}) 和 wwlr.LabelId in(#{showLabels}),其中 showLabels 是传进来一个字符串类型的参数,参数的样子是这样的 “4,44,514”,问题就出在这个参数传进来后 #和 $ 处理的方式是不一样的。

区别

1、#{} 是预编译处理,MyBatis 在处理 #{} 时,它会将 sql 中的 #{ } 替换为?,然后调用 PreparedStatement 的 set 方法来赋值,传入字符串后,会在值两边加上单引号,如上面的值 “4,44,514” 就会变成 “ ‘4,44,514’ ”;

2、${} 是字符串替换, MyBatis 在处理 ${} 时, 它会将 sql 中的 ${ } 替换为变量的值,传入的数据不会加两边加上单引号。

注意:使用 ${ } 会导致 sql 注入,不利于系统的安全性!

SQL 注入:就是通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。常见的有匿名登录(在登录框输入恶意的字符串)、借助异常获取数据库信息等

应用场合:

1、#{}:主要用户获取 DAO 中的参数数据, 在映射文件的 SQL 语句中出现 #{} 表达式, 底层会创建预编译的 SQL;

2、${}: 主要用于获取配置文件数据, DAO 接口中的参数信息, 当 $ 出现在映射文件的 SQL 语句中时创建的不是预编译的 SQL, 而是字符串的拼接, 有可能会导致 SQL 注入问题. 所以一般使用 $ 接收 dao 参数时, 这些参数一般是字段名, 表名等, 例如 order by {column}。

注:

${} 获取 DAO 参数数据时, 参数必须使用 @param 注解进行修饰或者使用下标或者参数 #{param1} 形式;

#{} 获取 DAO 参数数据时, 假如参数个数多于一个可有选择的使用 @param。

问题分析

其实刚开始我也没太去看 sql 里的 #和 $,我把 sql 放到数据库跑一切正常,所以我就将代码的执行 sql 输出到控制台了,具体是这么一个输出 sql 的配置文件:

输出后,终于发现了问题在哪里。。。。

看了上面的区别介绍,相信大家其实都应该知道区别在哪里,我们的问题在哪里,其实就是 sql 在 in 的时候 ,里面的数据被加了两个双引号。“wwlr.LabelId in(4,44,514)就会变成 wwlr.LabelId in(‘4,44,514’ );所以导致部分数据查不到了。

解决办法

1、快速解决

最快的方法就是把 #直接替换成 $,这样问题应该就可以解决了。

但是,我很无语,我确没有解决。

本地跑代码一点问题都没有,部署到公司的 docker 上问题一样没解决,给人的感觉就是代码根本没有从 #变 $。

大家都知道 $ 其实是有危险性,会容易被 sql 注入,具我所知道,我们公司的 docker 是会加一层防止 sql 注入的功能 ,所以不知道是不是这个功能把的 $ 无效掉了。

当然,我也没有去再到服务上打出 sql 来看一下,因为本来 $ 就是不太安全的,所以我换了一种方式处理。

2、foreach 标签的使用

foreach 标签主要用于构建 in 条件,他可以在 sql 中对集合进行迭代。

先来看看语法:

通过上图,大家也应该也了解和使用这个标签了吧。

那对于我们项目中的改造,其实就是把原来传进来的字符型参数变成 List,这样问题就完美的解决了,既实现了我们的功能 ,又解决了安全性问题。

原文链接:

https://m.toutiaocdn.com/i6685496024770806280

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis${}和#{}是用来替换SQL语句的参数的。它们的使用场合略有不同。 ${}是字符串替换,当MyBatis处理${}时,它会将SQL${}替换为变量的值,传入的数据不会加两边加上单引号。这种情况适用于需要动态拼接SQL语句的场景,比如动态指定表名或列名。 #{}是预编译处理,当MyBatis处理#{}时,它会将SQL#{}替换为?,然后调用PreparedStatement的set方法来赋值。传入的字符串会在值两边加上单引号,以确保安全性和正确性。这种情况适用于需要传入参数并进行预编译的场景,比如查询条件的参数。 总结起来,${}适用于动态拼接SQL语句的场景,而#{}适用于传入参数并进行预编译的场景。在使用时,我们需要根据具体的需求选择合适的方式来处理参数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Mybatis $#千万不要用](https://blog.csdn.net/wyouwd1/article/details/126130428)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Mybatis系列:Mybatis $# 千万不要用!](https://blog.csdn.net/Mrs_chens/article/details/90403648)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值