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

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

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

username传参一致的话,这两种执行的结果是一样的,但是这两种方式在动态sql解析阶段的处理是不一样的。

1、#{}

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

select * from t_user where username = ?;

而传入的参数将会经过PreparedStatement方法的强制类型检查和安全检查等处理,最后作为一个合法的字符串传入。

2、${}

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

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

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

3、#{}与${}两种方式对比

1)是否预防SQL注入

以上不同的处理方式可以看出

  • {} 预处理之后可以预防SQL注入

  • ${} 预编译之前就已经被替换,有被注入的风险

举个栗子:

如果传入的username 为 a' or '1=1,那么使用 ${} 处理后直接替换字符串的sql就解析为:

select * from t_user where username = 'a' or '1=1' ;

这样的话所有的用户数据就被查出来了,这样就属于SQL注入.

如果使用#{},经过sql动态解析和预编译,会把单引号转义为 \' 那么sql最终解析为:

select * from t_user where username = "a\' or \'1=1 ";//这样会查不出任何数据,有效阻止sql注入

有的业务场景经常用到模糊查询,也就是like处理,推荐使用以下处理方式:

t_user.username like #username#

if (!StringUtil.isEmpty(this.username)) {
table.setUsername("%" + this.username + "%");
}

或者也可以使用数据库函数进行连接处理:

select * from t_user u where username  like CONCAT('%', #username#, '%')

注意:

以上就可以发现在某些特定场景下只能用${},比如order by后的排序字段,表名、列名,因为需要替换为不变的常量。如果表名中使用#{}的话,会变成如下:

select * from #{tablename}-->tablename传参为t_user --->处理后变成 select * from 't_user',没有这样的表名,这样的话就会报错了,order by 同理。

2)性能考虑

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

总结:

能使用#{}的时候尽量使用#{}表名。
order by的排序字段作为变量时,使用${}。

来源:https://dwz.cn/tQwJGPbP

关注微信公众号【悟能之能】了解更多编程技巧。

回复"面经"获取面试资料

你真的了解MyBatis中${}和#{}的区别吗?的更多相关文章

  1. mybatis中#{}和${}的区别及order by的sql注入问题

    mybatis的#{}和${}的区别以及order by注入问题 原文  http://www.cnblogs.com/chyu/p/4389701.html   前言略,直奔主题.. #{}相当于j ...

  2. MyBatis中#{ }和${ }的区别,数据库优化遵循层次和查询方法

    MyBatis中#{ }和${ }的区别详解 1.#将传入的数据当成一个字符串,会对自动传入的数据加一个 双引号. 例如order by #id#,如果传入的值是111,那么解析成sql时变为orde ...

  3. mybatis中的#{}和${}区别

    mybatis中的#{}和${}区别 2017年05月19日 13:59:24 阅读数:16165 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #use ...

  4. Mybatis笔记八:MyBatis中#{}和${}的区别

    先给大家介绍下MyBatis中#{}和${}的区别,具体介绍如下: 1. $将传入的数据直接显示生成在sql中 2. #方式能够很大程度防止sql注入. 3.$方式无法防止Sql注入. 4.$方式一般 ...

  5. Mybatis与Ibatis的区别

    Mybatis与Ibatis的区别: 1.Mybatis实现了接口绑定,使用更加方便 在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 而Mybatis实现了DAO接口 ...

  6. mybatis与hibernate的区别持久层对比【面试题】

    Mybatis技术特点: 好处: 通过直接编写SQL语句,可以直接对SQL进行性能的优化: 学习门槛低,学习成本低.只要有SQL基础,就可以学习mybatis,而且很容易上手: 由于直接编写SQL语句 ...

  7. JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一

    系列博文: JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一 传送门 JavaWeb_(Mybatis框架)使用Mybatis对表进行增.删.改.查操作_ ...

  8. 【ORM】Mybatis与JPA的区别

    Mybatis与JPA的区别: 1.ORM映射不同: Mybatis是半自动的ORM框架,提供数据库与结果集的映射: JPA(Hibernate)是全自动的ORM框架,提供对象与数据库的映射: 2.可 ...

  9. Mybatis与Hibernate的区别

    首先简单介绍下两者的概念: Hibernate :Hibernate 是当前最流行的ORM框架,对数据库结构提供了较为完整的封装. Mybatis:Mybatis同样也是非常流行的ORM框架,主要着力 ...

随机推荐

  1. webgl图库研究(包括BabylonJS、Threejs、LayaboxJS、SceneJS、ThingJS等框架的特性、适用范围、支持格式、优缺点、相关网址)

    3D图库框架范围与示例 摘要: 为实现企业80%以上的生产数据进行智能转化,在烟草.造纸.能源.电力.机床.化肥等行业,赢得领袖企业青睐,助力企业构建AI赋能中心,实现智能化转型升级.“远舢文龙数据处 ...

  2. IOS应用无法下载、此时无法安装应用程序

    无法安装应用 app开发者,进行程序测试,重试还不行,就重新打包, 个人,更改wifi的dns 在“设置” –> “WiFi” –> 进入当前的WiFi 进入之后点击旁边的叹号,然后进入之 ...

  3. react开发中的小细节

    目前开始使用react余遇到的问题还不是很多,但还是希望总结一下. react中的属性prop: 在react中组件的父子组件的通信是基于prop的,当然对于底层的东西不是特别了解,但可以说一说它的基 ...

  4. dubbo文档笔记

    配置覆盖关系 以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似: 方法级优先,接口级次之,全局配置再次之. 如果级别一样,则消费 ...

  5. 【Java例题】2.7找零钱

    7.为顾客找零钱时,希望选用的纸币张数最少. 例如73元,希望零钱的面值为五十元1张,二十元1张,一元3张. 设零钱面值有五十元.二十元.十元.五元和一元, 请编写程序,用户输入100以下的数, 计算 ...

  6. 值得花费一周研究的算法 -- KMP算法(indexOf)

    KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...

  7. [Spring cloud 一步步实现广告系统] 16. 增量索引实现以及投送数据到MQ(kafka)

    实现增量数据索引 上一节中,我们为实现增量索引的加载做了充足的准备,使用到mysql-binlog-connector-java 开源组件来实现MySQL 的binlog监听,关于binlog的相关知 ...

  8. JavaWeb——使用会话维持状态2

    在这次的例子里面,将完成一类似购物车的功能,在客户访问网站的时候,会选中自己将要购买的商品,而购物车将始终维持着商品的状态,会话将联系起选择第一个商品(第一个请求),选择其他商品(其他请求)以及付款等 ...

  9. Flink 源码解析 —— 如何获取 JobGraph?

    JobGraph https://t.zsxq.com/naaMf6y 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac 上搭建 F ...

  10. String关键字

    关于String和new String()见我写的前一篇博客 String和new String()的区别 1.String的"+"运算 a.String str = " ...