MyBatis动态sql之${}和#{}区别

10 篇文章 0 订阅
4 篇文章 0 订阅

动态sql是mybatis的主要特性之一。在mapper中定义的参数传到xml中之后,在查询之前mybatis会对其进行动态解析。

mybatis提供了两种支持动态sql的语法:#{} 和 ${}。

select * from t_user where username = '${username}' and password='${password}';
select * from t_user where username = #{username} and password=#{password};

如果传值是一样的话,#{} 和 ${}的运行结果是一样的,但是在SQL解析阶段的处理是不一样的

1、#{}

解析为一个JDBC预编译语句(prepared statement)的参数标记符,把参数部分用占位符 ? 代替。
动态解析为:

select * from t_user where username = ? and password = ?;

就相当于JDBC 的prepared statement

2、${}

这种方式只会做简单的字符串替换,在动态SQL解析阶段将会进行变量替换,假如传递的参数为二师兄,最后相当于:

select * from t_user where username = '二师兄'  and password='123456';

这样在预编译之前的sql语句已经不包含变量了,因此可以看出 ${} 变量的替换阶段是在动态SQL解析阶段。

#{} 和 ${}比较 可以有效的预防SQL注入

举个例子:
如果传入的username为张三’# password为 123456

如果使用的是${}的话 最后的SQL为:

select* from users where username='张三'#' and password='123456'

可以看到 username=‘张三’ 之后是一个#
而在SQL中#是注释的意思,所以这条语句真正发挥作用的部分就是:select* from users where username=‘张三’ 就直接变成了一条查找张三 的语句,完全不用经过密码验证,这样就属于SQL注入!
但是如果使用的是#{},就可以避免这个问题。
因为经过sql动态解析和预编译,会把单引号转义为 ’ 那么sql最终解析为:

select* from users where username='张三\'#' and password='123456'

这样就查不出任何数据,有效阻止sql注入

性能考虑

因为预编译语句对象可以重复利用,把一个sql预编译后产生的PreparedStatement对象缓存下来,下次对于同一个sql,可以直接使用缓存的PreparedStatement对象,mybatis默认情况下,对所有的sql进行预编译,这样的话 #{}的处理方式性能会相对高些。
总结:

能使用#{}的时候尽量使用#{}!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值