你真的了解MyBatis中${}和#{}的区别吗?
动态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中${}和#{}的区别吗?的更多相关文章
- mybatis中#{}和${}的区别及order by的sql注入问题
mybatis的#{}和${}的区别以及order by注入问题 原文 http://www.cnblogs.com/chyu/p/4389701.html 前言略,直奔主题.. #{}相当于j ...
- MyBatis中#{ }和${ }的区别,数据库优化遵循层次和查询方法
MyBatis中#{ }和${ }的区别详解 1.#将传入的数据当成一个字符串,会对自动传入的数据加一个 双引号. 例如order by #id#,如果传入的值是111,那么解析成sql时变为orde ...
- mybatis中的#{}和${}区别
mybatis中的#{}和${}区别 2017年05月19日 13:59:24 阅读数:16165 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号.如:order by #use ...
- Mybatis笔记八:MyBatis中#{}和${}的区别
先给大家介绍下MyBatis中#{}和${}的区别,具体介绍如下: 1. $将传入的数据直接显示生成在sql中 2. #方式能够很大程度防止sql注入. 3.$方式无法防止Sql注入. 4.$方式一般 ...
- Mybatis与Ibatis的区别
Mybatis与Ibatis的区别: 1.Mybatis实现了接口绑定,使用更加方便 在ibatis2.x中我们需要在DAO的实现类中指定具体对应哪个xml映射文件, 而Mybatis实现了DAO接口 ...
- mybatis与hibernate的区别持久层对比【面试题】
Mybatis技术特点: 好处: 通过直接编写SQL语句,可以直接对SQL进行性能的优化: 学习门槛低,学习成本低.只要有SQL基础,就可以学习mybatis,而且很容易上手: 由于直接编写SQL语句 ...
- JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一
系列博文: JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一 传送门 JavaWeb_(Mybatis框架)使用Mybatis对表进行增.删.改.查操作_ ...
- 【ORM】Mybatis与JPA的区别
Mybatis与JPA的区别: 1.ORM映射不同: Mybatis是半自动的ORM框架,提供数据库与结果集的映射: JPA(Hibernate)是全自动的ORM框架,提供对象与数据库的映射: 2.可 ...
- Mybatis与Hibernate的区别
首先简单介绍下两者的概念: Hibernate :Hibernate 是当前最流行的ORM框架,对数据库结构提供了较为完整的封装. Mybatis:Mybatis同样也是非常流行的ORM框架,主要着力 ...
随机推荐
- rabbitMQ_integeration_spring(七)
参考了其他博主的资料,整理成完整的代码,直接拷贝就可以测试. 一.创建一个properties文件 mq.host=127.0.0.1 mq.username=root mq.password=roo ...
- spring的jdbcTemplate的使用
转载:http://1358440610-qq-com.iteye.com/blog/1826816 一.首先配置JdbcTemplate: 要使用Jdbctemplate 对象来完成jdbc 操作. ...
- poj 1131 Octal Fractions(高精度小数进制转换) Java
虽然题目那么长其实就是把8进制的浮点数转换成10进制,为了练习Java Biginteger 类 我这里用的是Java,也可以用数组模拟. import java.math.BigDecimal; i ...
- wscript.shell 使用
<%@ Page Language="VB" validateRequest = "false" aspcompat = "true" ...
- go单元测试
testing模块 测试代码放在当前包以_test.go结尾的文件中 测试函数以Test为名称前缀 测试命令(go test) 正常编译操作(go build/install)会忽略测试文件 单例模式 ...
- 直方图均衡基本原理及Python实现
1. 基本原理 通过一个变换,将输入图像的灰度级转换为`均匀分布`,变换后的灰度级的概率密度函数为 $$P_s(s) = \frac{1}{L-1}$$ 直方图均衡的变换为 $$s = T(r) = ...
- The introduction of the book American daily English notes (enlarged edition)
After reading the book of American daily English notes written by Linkun Yang[1], I think I should a ...
- Spring IoC源码解析之invokeBeanFactoryPostProcessors
一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...
- Android实现多语言so easy
微信公众号:CodingAndroid CSDN:http://blog.csdn.net/xinpengfei521声明:本文由CodingAndroid原创,未经授权,不可随意转载! 最近,我们公 ...
- ES 27 - Elasticsearch脚本的使用实践
目录 1 关于脚本 2 脚本使用的最佳实践 2.1 创建脚本并存储 2.2 脚本的缓存 2.3 Script Field - 脚本字段 本文以 ES 6.6.0 版本为例进行演示. 1 关于脚本 ES ...
