工作发狂:Mybatis 中$和#千万不要乱用!

简介: 你都使用过没?

阅读本文大概需要 2.2 分钟。

作者:程序猿的内心独白

开头

这是一次代码优化过程中发现的问题,在功能优化后发现部分数据查不到出来了,问题就在于一条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,这样问题就完美的解决了,既实现了我们的功能 ,又解决了安全性问题。

·END·

程序员的成长之路

路虽远,行则必至

相关文章
|
6月前
|
缓存 Java 数据库连接
干翻Mybatis源码系列之第八篇:Mybatis提供的缓存方案细节注意
干翻Mybatis源码系列之第八篇:Mybatis提供的缓存方案细节注意
|
6月前
|
XML Java 数据库连接
干翻Mybatis源码系列之第五篇:Mybatis中核心运行机制超级详细版
干翻Mybatis源码系列之第五篇:Mybatis中核心运行机制超级详细版
|
6月前
|
存储 SQL Java
干翻Mybatis源码系列之第十二篇:自写Mybatis拦截器实现分页操作
干翻Mybatis源码系列之第十二篇:自写Mybatis拦截器实现分页操作
|
存储 SQL XML
五.吃透Mybatis源码-面试官问我mapper映射器是如何工作的
面试官:你说一下为什么Mapper映射器是一个interface,而我们却可以直接调用它的方法,还能执行对应的SQL。额…也许你不知道,也许你知道个大概,本篇文章将带你从源码的角度彻彻底底理解Mybatis的Mapper映射器
|
Java 关系型数据库 MySQL
玩“公主焊接”,顺便学习学习数据库关系映射与Spring Boot中MyBatis(SSM框架)的级联操作(bushi)
玩“公主焊接”,顺便学习学习数据库关系映射与Spring Boot中MyBatis(SSM框架)的级联操作(bushi)
355 0
|
SQL 缓存 Java
2022最新最全MyBatis(简单全面,一发入魂,内容超详细)
一、MyBatis简介 1、MyBatis历史 2、MyBatis特性 3、MyBatis下载 4、和其它持久化层技术对比 JDBC Hibernate 和 JPA MyBatis 二、搭建MyBatis 1、开发环境 2、创建maven工程 a>打包方式:jar b>引入依赖 3、创建MyBatis的核心配置文件 4、创建mapper接口 5、创建MyBatis的映射文件 6、通过junit测试功能 7、加入log4j日志功能 a>加入依赖 b>加入log4j的配置文件 三、核心配置文件详解 四、MyBatis的增删改查 五、MyBatis获取参数
2022最新最全MyBatis(简单全面,一发入魂,内容超详细)
|
SQL Java 数据库连接
mybatis plus注意的地方
1 可能你会觉得奇怪,明明我创建表的时候,设置id自增从1开始。自增主键,数据库设置了自增主键后,po类需要增加@TableId(type = IdType.AUTO),或者不要id字段才能生效。
145 0
mybatis plus注意的地方
|
SQL 存储 缓存
Mybatis的执行流程,写的也太全了吧!(中)
Mybatis的执行流程,写的也太全了吧!
108 0
Mybatis的执行流程,写的也太全了吧!(中)
|
XML 存储 SQL
Mybatis的执行流程,写的也太全了吧!(上)
Mybatis的执行流程,写的也太全了吧!
117 0
Mybatis的执行流程,写的也太全了吧!(上)
|
SQL Java 数据库连接
Mybatis的执行流程,写的也太全了吧!(下)
Mybatis的执行流程,写的也太全了吧!
153 0
Mybatis的执行流程,写的也太全了吧!(下)