Mybatis#号和$的区别,面试时如何不尴尬的回答

mybatis#号和$的区别是什么,想必大家在面试过程中或多或少都会遇到过这个问题吧!
当面试官问到这个问题的时候,是不是答完:“#号可以防止sql注入,$不可以防止sql注入”。就草草了事了呢?

这么回答正确,没问题!可你有没有想过这么简单的回答有什么意义呢?只能证明你知道答案,对于你个人的能力却毫无展现。

这时对于一个有几年工作经验的你,心中是否在想这么简单的问题还要问吗?是面试官在怀疑你的能力,还是面试官不知道问什么?
为了避免一句话就答完这个问题的尴尬,同时又能展现你的能力,阿灯为大家准备了如下参考。

1、谈发现

      在日常开发中,我们难免会根据控制台或日志打印出的sql语句进行验证和调试。但是往往我们在控制台看到的sql语句,并不是完整带参数的语句而是带有?号占位符的。如下:

mybatis语句:select id from user where name=#{name}
select id from user where name=?

我们复制语句后,想要单独执行sql语句,这时就需要手动的将占位符替换成相应的参数。如果遇到参数过多的情况,那么,我们手动替换时不仅会感到很繁琐,同时也会很浪费时间。这时我们就会想,能不能在控制台打印出不带占位符的完整sql语句,下面阿灯给大家提供点打印完整sql的方式:

    可以通过P6Spy跟踪sql的执行情况,只需要添加maven依赖和一个spy.properties配置文件即可

maven依赖如下

 <dependency>    <groupId>p6spy</groupId>    <artifactId>p6spy</artifactId>    <version>2.1.4</version> </dependency> 

    还有一种简单的方式,在IDEA中安装MyBatis Log Plugin 这时就可以通过控制台看到不带占位符的完整sql语句了。如下:

select id from user where name='admin'

    当然其他方式也有,大家可自行研究。

这时我们发现打印出的sql语句就是带有参数的完整sql语句了。在这种情况下复制调试,是不是很方便呢?

    到这里我们就会发现使用${}时,sql语句是按照参数原样拼接的。而使用#{}sql语句的参数上会多出单引号 ‘

2、谈研究

     我们在第一步会发现$和#号的sql语句输出结果的参数,有不加单引号和加单引号的区别。

    那么阿灯问大家个问题:select * from user where name=${name}这样的语句可以写吗? 不明确的,可以试下。

    答案当然是不可以的,那么select * from user where name='${name}'又和select * from user where name=#{name} 有什么区别呢?最终的sql语句不都是在name参数上加了引号了吗?表面上看貌似是,但如果name的值为:admin' or '1'='1,那么最终sql是不是一样呢?

    sql的最终结果是:$的sql原样输出,而#号的结果如下:

select * from user where name='admin'' or ''1''=''1'

    我们从#号的sql最终结果来看,会发现参数中的单引号都被进行了转义,这时,大家便会想到sql防止sql注入的问题了吧,因此可以说明“#号可以防止sql注入,$不可以防止sql注入”。#号防止sql注入的原理就是对参数及参数中的特殊字符进行了转义,从而达到防止sql注入的效果。

    此时,我们回顾下,mybatis的底层是什么?jdbc啊。我们可以联想到jdbc中的Statement对象和 PrepareStatement对象。而mybatis的$符就是对Statement语句进行的封装处理,#号就是对 PrepareStatement语句进行的封装处理。因此达到实现不同效果和目的的。

    到这里我们就不难跟踪到上面的单引号是在哪里进行转义的了。我们可以翻看jdbc的源码,由于是参数设置,当然要看set方法了。简单截个图,源码大家还是自己去翻吧setString方法里。

 

3、谈应用

       在实际开发中,我们使用#号的居多,各种条件查询。而$符号也在使用,比如由于数据量的原因,我们将数据进行按业务分表,在表名不同字段相同的情况,为了简化代码量和灵活度采用动态表名的查询

select * from ${tableName}

    再如为了灵活排序而使用的 order by ${filedName}等多种情况。

    但有一点需要注意,为了保证安全的情况,在使用$时,尽量避免动态字段从客户端显示传递使用。

 

通过以上的回答和交流,面试官是不是会感觉你不是小白,同时在工作和学习中很用心的一个开发者呢?

采用此种方式介绍的目的,是为了让大家在工作和学习中要善于发现、思考和总结和尝试。运用联想和为什么的方法去定向解决问题。当然文中可能有许多不足之处,望大家指正交流。

                                     扫描或长按下方二维码关注公众号,持久关注阿灯的动态

                                                        

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值