面试题:Mybatis中 $ 和 # 的区别? 您所在的位置:网站首页 公示和公布的区别是什么 面试题:Mybatis中 $ 和 # 的区别?

面试题:Mybatis中 $ 和 # 的区别?

2023-03-11 02:24| 来源: 网络整理| 查看: 265

前言:

能看到这里的各位,想必都是java程序员吧,面试的时候估计大部分的人,都会从面试官口中听到这个面试问题吧?

你当时是怎么回答的呢?回答的自信吗?回答的让自己和面试官满意吗?是否知道怎么在自己的项目中用#{}和${}符号呢?

如果以上问题你都回答否的话,我想看过这篇文章可以让你回答是。

问题:请说明mybatis中#和$的区别?

答:

相同点:

都能取到变量的值。

不同点:

#可以实现预编译,会先把#{变量}编译成?,在执行时再取值,可以防止sql注入。

$是直接进行字符串替换。

如果你只是回答了以上内容,只能算是勉强及格,但是会让面试官觉得你有背面试题的嫌疑。怎么让面试官觉得你有点东西呢?你可能需要理解下面的内容,才能更好的跟面试官扯皮:

1.1 #符号解析:

上面说了#可以实现预编译,那你知道预编译过程中mybatis都做了啥吗,其实主要表现在数据类型检查和安全检查两部分:

数据类型检查表现在:若检测到为数值类型,就不加引号,即?;若检测到位字符串类型,就加上引号,即'?'。

安全检查表现在:若变量的值带有引号,会对引号进行转义处理,这样可以防止sql注入。

1.2 #符号的应用场景:

需要在sql映射文件中动态拼接sql时的开发场景,比如传入多个变量进行条件查询、传入一个POJO进行数据插入等。

2.1 $符号解析:

$符号主要用于传入的参数是sql片段的场景下,会直接进行字符串替换,完成了sql的拼接。比如我们不在sql映射文件中利用mybatis的动态sql来拼接sql,而是在java代码中去动态的拼接sql,然后将拼接的sql片段作为变量传入sql映射文件。上面也说了$符号只是进行字符串的替换,如果我们传入一个sql片段的话,相当于直接进行了sql拼接,就不用在sql映射文件中利用mybatis提供的动态sql标签来拼接sql了。甚至可以这样:

${sql片段}

对于这样外部传入的sql,就不能使用#{},上面也说了,#{}会进行预编译,检测到该sql片段是个字符串,就会加上引号,即'sql片段',这样就是字符串了而不是sql,执行会报错。

可以说,${}让以前在java代码中动态拼接sql的麻烦时代,在mybatis中成为了可能,mybatis想的真周到啊,嘿嘿。

依据$适用于传入sql片段的情况,我们可以将数据表字段名、表名、数据库名等传入,来进行sql拼接,如:

2.2 $符号的应用场景:

比如:select ${columns} from ${tableName},假设columns变量的值是userName,age 。tableName变量的值是user,那么该sql语句就会被解析成:select userName,age from user

比如有这样一个需求:对于后台管理系统的table列,想让用户选择展示哪些列,不展示哪些列,或者根据权限来分配不同的用户可以看到哪些列?

这个需求正好用到了$符号,我们可以将每个用户对于一个table能看到哪些列,存储到数据表中,对该数据表进行crud,每次展示列表的时候,先根据用户ID和table类型,到数据表中查询该用户对该table能看到的列名(字段名)列表,然后将该字段名列表作为sql片段传入mybatis进行查询,此时就必须得用到$符号,而不能用#符号了。

2.3 $符号的sql注入问题:

用${}时要特别注意sql注入的风险,如果该sql片段是根据用户的输入拼接的,要注意检查sql注入的问题,防止数据的泄露与丢失!

反面案例:

假如这个sql:select * from ${tableName} where name = ${name}

如果tableName的值为 user; delete user; --,该sql最终解析成select * from user; delete user; -- where name = xxx,结果查询了整张表,然后把user表给删了...

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有