为什么Mybatis中#{}和${}不同

引言

我们都知道在Mybatis中有两种获取参数的方式,#{}和${},面试中也是一个经常问的点,今天我们就来深究一下这两种方式背后的一些奥秘,我们会从表现形式和背后原理两个部分来分析,让你知道哪里不同以及为什么不同。

表现形式

1 #{}可以防止sql注入,${}会有sql注入问题
2 #{}使用的是占位符的形式,而${}采用的是字符串拼接的方式

背后原理

1 我们来实际看一个例子。
采用${}方式进行登录验证
模拟前端拿到的参数,这里我们假设黑客不知道密码,只使用用户名进行登录,我们看一下${}能不能拦住他。
在这里插入图片描述
mapper.xml这样写
在这里插入图片描述

结果如下
在这里插入图片描述
这里并没有出现sql注入问题,问题出在哪呢?仔细观察我们的mapper.xml文件中,取值的操作是’ ${arg0} ‘这样写的,两边有单引号,黑客输入的sql其实并没有执行,而是被当作字符串解析了。那么为什么我们要’${arg0}’ 这么写呢?因为我们取得值在mysql中是字符串存储的,加上’ '来查询才可以查出来。

我们改一下,取值的时候直接${arg0} 写,再进行一次测试我们看看结果。
在这里插入图片描述
显然黑客成功了,也就完成了我们所说的sql注入的攻击。

所以我们说${}确实会有sql注入问题,但并不一定会发生,很大程度上取决与程序员怎么写sql。

而对于#{}来说,因为是使用占位符的方式,mybatis会将上面的sql下面这样子,然后把两个参数填进去,所有避免了sql注入的问题。
在这里插入图片描述

2 从mybatis的官方文档上我们可以找到,当使用#{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样),而使用${}使用的底层创建的是Statment对象,我们来复习一下这两个对象是怎么使用的。

使用statement

Statement stmt = connect.createStatement();
String sql= "SELECT * FROM 表名 WHERE 字段=值";
//去执行sql语句
ResultSet rs = stmt.executeUpdate(sql);

使用preparstatement

         String Sql = "INSERT INTO qiuer(sName,sAge,sClass) VALUES (?,?,?)";
//            预先执行指令
            PreparedStatement prmt = connection.prepareStatement(Sql);
//          用来向prmt中的sql语句放入 数据 可以是从页面来的 可以是从后台来的
            prmt.setString(1,qiuer.getsName());
            prmt.setInt(2,qiuer.getsAge());
            prmt.setString(3,qiuer.getsClass());
//            执行prmt指令  增删改 语句
            prmt.executeUpdate();
    //        查询语句
//          prmt.executeQuery()

不知道看到这里大家有没有明白为什么#{}使用的是占位符的形式,而${}采用的是字符串拼接的方式,因为它们的底层就是这样调用的对象就是这样写的。

再思考
说到这里可能有人回问,看起来#{}比${}要好用很多呀,而且实际开发中也是用#{},老师也说能用#{}就不用${},那么${}存在的意义是什么呢?
因为有的查询使用#{}是不行的,举个例子
需求,通过传入的参数作为表名去查询所有的数据
mapper.xml这样写
在这里插入图片描述
解析后就变成 select * from “test”;
执行就会报错
而改成这样
在这里插入图片描述
解析后就变成 select * from test; 才可以执行成功

小结
上述就是Mybatis中#{}和${}的不同点,这是”十万个为什么“的第二篇文章,写这篇文章也是验证了实践出真知,下次再有人说${}会导致sql注入就把这篇文章扔给他,自己动手试一试便知。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值