0


MyBatis中的#和$有什么区别

一. 什么是MyBatis

MyBatis是一款优秀的持久层框架,特别是在国内(国外据说还是 Hibernate 的天下)非常的流行,我们常说的SSM组合中的M指的就是MyBatis。

MyBatis支持定制化SQL、存储过程以及高级映射等多种特性,单纯从代码上来看,MyBatis避免了几乎所有的JDBC代码和手动设置参数以及手动处理结果集。而且MyBatis的使用也非常方便,可以通过简单的XML或注解来配置和映射数据信息。

对MyBatis不熟悉的小伙伴,可以私信百泽老师,我们有免费的MyBatis手把手教学视频送给你哦~

二. 什么是动态 SQL

MyBatis的强大特性之一便是它的动态SQL,凡是使用过JDBC或其他类似框架,如DBUtils、JdbcTemplate等数据库操作工具的同学,都能体会到根据不同条件拼接SQL语句是有多么的痛苦!我们不仅要拼接SQL,还要拼接参数,特别费事,而且拼接的时候还要确保不能忘了必要的空格,还要注意省略掉列名列表最后的逗号.......操作过这样代码的小伙伴应该都明白这里的弊端。然而利用MyBatis的动态SQL特性,就可以彻底摆脱这种痛苦。

MyBatis 支持使用 ${} 和 #{}两种符号来进行动态SQL的拼接,可能有些人没有留意到,认为 ${} 和 #{} 的作用是差不多的,其实这两者的功能虽然相似,但区别是比较大的!而且,关于这两者的区别,也是Mybatis面试时的一个高频问题,今天百泽老师就带各位一起来看看两者的区别到底有哪些。

三. #$

  1. 基本用法

我们先来了解一下 #$ 的基本用法。这两个都可以进行动态 SQL 的拼接,但用法上略微有一些差异。

我们先来看 # 的用法:

select * from t_user where name = #{param}

如果想执行相同的 SQL,用 $ 写法如下:

select * from t_user where name = '${param}'

眼尖的小伙伴可能已经发现,使用 $ 比使用 # 多了一对单引号,为什么要这样呢?这里就涉及到了两者的第一个区别了:

  1. 会进行预编译,而且会进行类型匹配,参数是在编译之后填充进去的,所以不需要加上单引号;

  2. $ 不会进行数据类型的匹配,只是单纯地进行字符串的拼接,所以要自己手动加上单引号,否则最终拼接出来的SQL语句就不对了。

用过JDBC的小伙伴可能会知道,这就跟JDBC中的PrepareStatement和Statement的区别是一样的,使用 # 就相当于使用 PrepareStatement,而使用 $ 就相当于使用 Statement。

好啦,这就是两者的第一个区别!那么还有其他的区别吗?在讲第二个区别之前,百泽老师先给小伙伴们介绍一下什么是SQL注入。

2. 什么是SQL注入

在我们的日常开发中,对于网页上的操作,归根结底无外乎就是增删改查,所以有很多同行都自嘲自己是CURD工程师。

在CURD的过程中,以SQL查询为例,假设我们想根据用户名和密码查询某一个用户是否存在,现在要让用户在前端根据用户名和密码进行查询。

现在假设我们后台的SQL语句如下:

select * from user where username='${username}' and password='${password}'

前端网页有两个输入框,一个是用户名输入框,另一个是密码输入框。假设用户老老实实地输入用户名为zhangsan,密码为123,那么最终生成的SQL语句如下:

select * from user where username='zhangsan' and password='123'

以上过程似乎很完美!

但是!!!要是有人不老实呢?

假设用户输入的用户名是 zhangsan' or 1=1 #,密码则随意给了个值 111,那么最终生成的 SQL语句可能就是下面这样了:

select * from user where username='zhangsan' or 1=1 #' and password='123'

大家知道,# 在 SQL语句中的含义是注释,#后面的SQL内容是不执行的。所以这个SQL无论怎么执行,最终都会返回true。这就是所谓的SQL注入了。

如果我们想要防止SQL注入,其实有很多解决办法,其中最直接的一种,就是不要使用$符号来拼接 SQL语句!

3. #$的区别

看了上面的例子,现在大家就明白了,相比于 $ ,#有一个重要的作用,那就是可以防止SQL注入!

  1. 变量传递时,必须使用#。使用 #{} 就等于使用了JDBC 中 PrepareStatement 这种占位符的形式,既可以提高SQL的执行效率,又可以防止SQL注入等问题。

  2. $ 只是一种简单的字符串拼接,要特别小心 SQL注入的问题。如果我们在项目中使用了$,那么可以自定义过滤器或者通过Druid等工具,来防止SQL注入。

  3. 如果在一个场景中,既能使用 # 又能使用 $,那么建议首选 #。

四. 什么情况下只能用$

另外有一个特殊场景只能用$!那就是将数据库对象作为参数传递,其中最常见的就是 group by了。假设我们现在想要对某个表进行排序查询,但参与排序的字段并不确定,而是要通过前端参数传递过来,那么此时就必须使用 $ 了!因为 # 预处理之后,会把数据库中的字段名识别为字符串,进而会出错,如下所示:

select count(*) from user group by ${param}

当然,上面这只是其中的一个例子,实际情况是,只要遇到将数据库的字段名作为参数传递的情况,都得用 $!

五. 小结

最后,百泽老师再来给大家简单总结一下两者的区别:

  1. 会进行预编译,而且会进行类型匹配,参数是在编译之后填充进去的,所以不需要加上单引号;

  2. $ 不会进行数据类型匹配,只是一种单纯的字符串拼接,所以要自己手动加上单引号,否则最终拼接出来的 SQL语句会有问题。不过也要看具体的使用场景,如果参数是列名,就不用加单引号;

  3. # 能够预防 SQL 注入问题,$ 不能;

  4. 当需要遇到将数据库的字段名作为参数传递时,应该使用用 $。

现在,你知道Mybatis中的#与$有哪些区别了吗?

标签: mybatis java mysql

本文转载自: https://blog.csdn.net/GUDUzhongliang/article/details/128930743
版权归原作者 千锋教育官方 所有, 如有侵权,请联系我们删除。

“MyBatis中的#和$有什么区别”的评论:

还没有评论