工作发狂: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<Integer>,这样问题就完美的解决了,既实现了我们的功能 ,又解决了安全性问题。
原文链接:
https://m.toutiaocdn.com/i6685496024770806280
·END·
程序员的成长之路
路虽远,行则必至
本文原发于 同名微信公众号「程序员的成长之路」,回复「1024」你懂得,给个赞呗。
回复 [ 520 ] 领取程序员最佳学习方式
回复 [ 256 ] 查看 Java 程序员成长规划
往期精彩回顾
工作发狂:Mybatis 中$和#千万不要乱用!的更多相关文章
- SpringMVC的工作流程?Mybatis和hibernate区别?
SpringMVC的工作流程?1. 用户发送请求至前端控制器DispatcherServlet2. DispatcherServlet收到请求调用HandlerMapping处理器映射器.3. 处理器 ...
- 记录一次bug解决过程:mybatis中$和#的使用
一.总结 mybatis中使用sqlMap进行sql查询时,经常需要动态传递参数.动态SQL是mybatis的强大特性之一,也是它优于其他ORM框架的一个重要原因.mybatis在对sql语句进行预编 ...
- @MyBatis中的if...else...
<select id="selectSelective" resultMap="xxx" parameterType="xxx"> ...
- PageHelper在Mybatis中的使用
环境:Spring 4.2.1 Mybatis 3.2.8 pagehelper 5.1.2 Mybatis官方教程:https://github.com/pagehelper/Mybatis-Pag ...
- VBS读取txt文档数据查找Excel中单元格数据符合条件的剪切到工作表2中
Dim fso,f,a set oExcel = CreateObject( "Excel.Application" ) oExcel.Visible = false '4) 打开 ...
- Redis 千万不要乱用KEYS命令,不然会挨打的
Redis现如今使用的场景越来越多?如何批量删除key呢? 有人说用KEYS命令,刚开始学Redis的时候就是用这个命令列出库中键. KEYS命令要谨慎使用. 为何?客观别急,我们先一步步来看. KE ...
- LocalDateTime整合到SpringBoot + MyBatis中
啥也不说先贴两个代码: 一:MVC层配置 @Configuration public class JacksonConfig { /** 默认日期时间格式 */ public static final ...
- MyBatis从入门到精通(第9章):Spring集成MyBatis(中)
MyBatis从入门到精通(第9章):Spring集成MyBatis(中) 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法.应该将应用自身的设计和具体 ...
- Mybatis中的# 与 $
我们说MyBatis有两种注入参数的方式, - 一种是#{} - 另一种是${} 这两种从使用功能来看差距不大,那为什么会强推使用#? ${}使用的是拼接字符串,#{}使用的是占位符的方法,经过了处理 ...
随机推荐
- angular js根据json文件动态生成路由状态
项目上有一个新需求,就是需要根据json文件动态生成路由状态,查阅了一下资料,现在总结一下发出来: 首先项目用到的是angular的UI-路由,所以必须引入angular.js和angular-ui- ...
- java基本结构
前言 Java文件的运行过程: 1,javac.exe:编译器 2,java.exe:解释器 微软shell下运行实例: C:\Users\Administrator>cd D:\文档\JAVA ...
- Vue学习之webpack调用第三方loader(十五)
---恢复内容开始--- 一.webpack 默认只能打包处理 JS 类型的文件,无法处理 其他的非 JS 类型的文件: 如果非要处理 非 JS 类型的文件,我们需要手动安装一些 合适 第三方 lo ...
- pychrom注册码
http://angame.top/wx/web/zhucema/ YZVR7WDLV8-eyJsaWNlbnNlSWQiOiJZWlZSN1dETFY4IiwibGljZW5zZWVOYW1lIjo ...
- [LeetCode] 543. 二叉树的直径 ☆(递归、数最大深度)
描述 给定一棵二叉树,你需要计算它的直径长度.一棵二叉树的直径长度是任意两个结点路径长度中的最大值.这条路径可能穿过根结点. 示例 :给定二叉树 1 / \ 2 3 / \ 4 5 返回 3, 它的长 ...
- nginx小结
1.nginx下部署网站 网站为:http://10.1.75.177:8000 nginx端口为80 配置如下: user nginx; worker_processes auto; error_l ...
- layui加载显示问题
1.layui.config({ base: '../layuiadmin/' //静态资源所在路径 }).extend({ index: 'lib/index' //主入口模块 }).use(['i ...
- docker中基于centos镜像部署lnmp环境 php7.3 mysql8.0 最新版
Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源. Docker可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的Linux机器上 ...
- Linux-负载均衡HAproxy
负载均衡之HAProxy 现在常用的三大开源软件负载均衡器分别是Nginx.LVS.HAProxy.三大软件特点如下: LVS负载均衡的特点: ()抗负载能力强,抗负载能力强.性能高.能达到F5硬件的 ...
- 攻防世界WEB高手进阶之python_template_injection
python模板注入 看了一堆文章,也不是看的很明白,反而把题目做出来了 大概思路如下 简单探测 http://111.198.29.45:42611/{{7+7}} 返回 说明服务器执行了{{}}里 ...