mybatis中的#和$的区别

经常碰到这样的面试题目:#{}和${}的区别是什么?

正确的答案是:#{}是预编译处理,${}是字符串替换。

(1)mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值。

(2)mybatis在处理${}时,就是把${}替换成变量的值。

(3)使用#{}可以有效的防止SQL注入,提高系统安全性。原因在于:预编译机制。预编译完成之后,SQL的结构已经固定,即便用户输入非法参数,也不会对SQL的结构产生影响,从而避免了潜在的安全风险。

(4)预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。

下面是菜鸟看的:

对于(1)和(2)的理解:

使用${}方式传入的参数,mybatis不会对它进行特殊处理,而使用#{}传进来的参数,mybatis默认会将其当成字符串。可能在赋值给如id=#{id}和id=${id}看不出多大区别,但是作为表名或字段参数时可以明显看出,可以看看下面的例子:
假设传入的参数为表名test

select * from #{table};

解析后是:

select * from "test";

select * from ${table};

解析后是:

select * from test;

很明显,前者多了字符串的引号,会失败,后者正常查询会成功;
所以对于传入分组(order)字段或者排序字段(order),应使用${},避免出现order by “id” 等情况。

对于第(3)(4)句话的理解:
#和$在预编译处理中是不一样的。#类似jdbc中的PreparedStatement,对于传入的参数,在预处理阶段会使用?代替,比如:

select * from student where id = ?;

待真正查询的时候即在数据库管理系统中(DBMS)才会代入参数。
而${}则是简单的替换,如下:

select * from student where id = 2;

总结:

1、能使用#{}的地方应尽量使用#{}

2、传参区别:
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值(8大原始值类型),#{}括号中可以是value或其它名称。如果parameterType传输pojo类型,#{}括号中是pojo中字段的名称。

${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。如果parameterType传输pojo类型,${}括号中是pojo中字段的名称。

3、${}导致sql注入的例子:
${ } 在预编译之前已经被变量替换了,这会存在 sql 注入问题。例如,如下的 sql:

select * from ${tableName} where name = #{name}

假如,我们的参数 tableName 为 user; delete user; --,那么 SQL 动态解析阶段之后,预编译之前的 sql 将变为:

select * from user; delete user; -- where name = ?;

– 之后的语句将作为注释,不起作用,因此本来的一条查询语句偷偷的包含了一个删除表数据的 SQL。

再简单讲讲sql预编译
定义:
​ sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。

为什么需要预编译
JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译

  • 预编译阶段可以优化 sql 的执行。
    预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。
  • 预编译语句对象可以重复利用。
    把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。

参考:
https://blog.csdn.net/yuan_qh/article/details/100810619
MyBatis动态sql之${}和#{}区别
sql注入小栗子

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值