SSM——4.Mybatis获取参数值的方式

目录

1.模糊查询

2.Mybatis获取参数值的两种方式

2.1概述

2.2具体分析

2.2.1#{}

2.2.2 ${}

2.2.3 小拓展

2.2.4 小注意

2.3执行时对比分析

2.4安全性的对比分析

 2.5什么时候使用${ }

 2.6如何选择使用#{ }还是${ }

2.7为什么#{ }可以防止sql注入


这篇文章我们将详细讲解一下Mybatis的2种参数注入方式,并通过实例来比较两者的区别。

1.模糊查询

在讲参数注入方式之前,我们先来看一下Mybatis的模糊查询如何写。

还是一样,我们首先来写UserDao.xml文件,代码如下:

    <select id="likeFind" parameterType="java.lang.String" resultType="com.qcby.entity.User">
        select * from user where username like '%${value}%'
    </select>

截图如下:

说明:细心的朋友会发现,第36行后面的参数注入与之前的有些不同,不用着急,这是Mybatis的另一种参数注入方式,是我们后面要重点讲的。

然后,我们来写接口(不给你代码了),截图如下:

 然后,我们来写测试方法,代码如下:

@Test
    public void likeFind(){
        List<User> users = mapper.likeFind("熊");
        for (User user:users) {
            System.out.println(user.toString());
        }
    }

截图如下:

 在测试之前,我们先来做一些配置,主要是做日志信息的配置。我们在sqlMapConfig.xml文件里面加入如下代码:

<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

截图如下:

 最后,让我们看一下测试结果:

这就是完整的日志记录及运行结果。

2.Mybatis获取参数值的两种方式

2.1概述

Mybatis获取参数值得两种方式:${ } 和 #{ }

#{}的本质是占位符赋值;${ }的本质是字符串拼接;

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;

#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段赋值时,可以自动添加单引号;

2.2具体分析

2.2.1#{}

首先,我们来分析 #{ }

我们的根据id进行查询的方法用的是#{ },我们来看一下它的输出情况:

这是我们的sql语句:

这是我们的输出日志及结果:

 可以看见,在我鼠标选中的那一行,后面是 id = ?,说明什么?说明我们sql语句中的 id=#{id} 后面的id是起占位作用的。我先把位置给你占着,然后你传参,然后再把参数放到这个位置上,这就是#{ }的一个流程。

我们可以再换一个例子来看一下:

这是sql语句:

 这是测试函数:

这是输出的日志及结果:

 

 我们现在来仔细分析一下:

正常的,能够在Navicat上运行的sql语句是这样的:select * from user where username = '张3'

而我们在编辑器上运行的sql语句是如上图所示,也就是说,我们的前半部分 和 张3 合并起来的时候,他自动的给我们加上了 ' ' 。现在我们懂了,#{ }是一种占位赋值的方式,在赋值的过程中,如果需要 ' ' ,它会自动的帮我们加上 ' ',从而保证sql的正常运行。它的流程还是那样,我先帮你占着位置,你传参,然后把参数放在我的位置上,然后根据参数类型来决定加不加 ' ' (这里的“ 如果需要 ' ' ” 我个人的理解是 它是根据赋值的内容进行判断的,如果是字符串型,就加,如果是Integer型,就不加,可以对比两张图看一下)

2.2.2 ${}

现在,我们再来看一下${ }。

我们的sql语句如下图所示:

测试方法如下:

 

然后,我们再来看一下输出的日志及结果:

 

 看我鼠标选中的那一行,它传输的是一条完整的sql语句,也就是直接将参数与sql语句拼接起来,然后传参。而#{ }是先传sql语句,再传参,最后拼接查询。这就二者的不同之处。

然后,我们将上述sql语句改一下,如图所示:

然后,测试方法写成这样:

 

 然后,我们再来看一下输出日志及结果:

 报错了,为什么?因为没有 ' ' ,这也说明了 ${ } 是一种拼接的方式,#{ } 是一种占位赋值的方式,其中拼接的方式有点笨,有点死板。

2.2.3 小拓展

如何用 #{ } 的方式来书写模糊查询?

答案如下,先看sql语句:

然后,我们看一下测试方法:

 最后,让我们看一下输出日志和结果:

 既然 #{ } 是占位赋值的方式,那我们就满足它它,用占位赋值的方式来打败它。

2.2.4 小注意

1. #{ value }  是占位赋值的方式,其中value是占位的字符,我们传的所有参数,不管什么样的,最终都是给了value。

2.${value } 是拼接的方式,我们的参数最终也是给了value,但是呢,如果有其他符合,比如%啊之类的,就要写在外面了。

3. #{value}与${value}我们可以把他们看成是一个整体,是不可拆分的,就是这样写的,是固定的,不能在里面加别的了

下面是我书写时范的一个错误,供大家参考:

毫无疑问,测试出现了问题。

2.3执行时对比分析

Mybatis获取参数的两种方式:#{ }占位赋值,${ } 字符串拼接

两者在运行时有什么区别?

#{ }是占位符:动态解析 -> 预编译 -> 执行

        预编译可以类比java类的编译,java类被编译成class文件,载入虚拟机,载入虚拟机的字节码文件可以先被编译成机器吗,那么在执行某行代码的时候就可以直接执行编译后的机器码,而不用从字节码开始编译再执行,那么执行效率就高了。这也是为啥热机状态比冷机状态可以抗更多负载的原因。

        sql的预编译也是一样的道理,在执行前就编译好,等执行时直接取编译结果去执行。省去编译时间。sql预编译后会在参数位置用占位符表示(也就是?表示)

        预编译:数据库驱动在发送sql和参数到DBMS之前,先对sql语句进行编译处理,之后DBMS则可以直接对sql进行处理,不需要再次编译,提高了性能。这一点mybatis 默认情况下,将对所有的 sql 进行预编译处理。

        预编译可以将多个操作步骤合并成一个步骤,一般而言,越复杂的sql,编译程度也会复杂,难度大,耗时,费性能,而预编译可以合并这些操作,预编译之后DBMS可以省去编译直接运行sql。

        预编译语句可以重复利用。把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。

${ }是拼接符:动态解析 -> 编译 -> 执行

        什么是字符串拼接?字符串拼接就是在我们向数据库发送sql语句之前,我们的sql语句就已经拼接好了。所以${ }的执行过程是先动态解析,然后直接编译,最后执行。没有预编译这一步

2.4安全性的对比分析

从安全性的角度分析,#{ }是更加安全的,因为${ }会引起sql注入的问题。

什么是sql注入问题?我们来看一下下面这个例子:

比如,我们在UserDao.xml文件中写下如下的语句:

 可是呢,我们在写测试方法时却写成下图这样:

这里入参入的是 "张三 or username = 李四"

这种通过传参就能改变SQL语句原本规则的操作就是SQL注入,这个在实际生产中当然是危险的,攻击者可以把SQL命令插入到Web表单的输入域或页面请求的查询字符串中,欺骗服务器执行恶意的SQL命令。

以上的情况就属于sql注入攻击。

可能有些同学还是不懂,那就说简单点,我们在模糊查询时,用户在搜索框中搜索到了不该搜索到的东西 就是sql注入(因为你入参出问题了啊,而#{ }会进行预编译,就能排除这个问题)

 2.5什么时候使用${ }

$:可以替换表名或者列名,你能确定数据是安全的,可以使用$

如下图所示情况:

 2.6如何选择使用#{ }还是${ }

下面给出我个人的几点建议:

1.能用 #{} 的地方就用 #{},尽量少用 ${}

2.表名作参数,或者order by 排序时用 ${}

3.传参时参数使用@Param("")注解,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值(相当于又加了一层密), 正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题)

2.7为什么#{ }可以防止sql注入

        mybatis的#{ }之所以能够预防sql注入是因为底层使用了PrepardStatment类的setString()方法来设置参数, 此方法会获取参数传递过来的每个字符,然后进行循环对比,如果发现有敏感字符(如:单引号、双引号等), 则会在上边加一个‘/’代表转义此符号,让其变成一个普通的字符串,不参与SQL语句的生成,达到预防sql注入的效果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L纸鸢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值