你真的了解Mybatis的${}和#{}吗?是否了解应用场景?
转自:https://www.cnblogs.com/mytzq/p/9321526.html
动态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解析阶段将会进行变量替换,假如传递的参数为Alice,最终处理结果如下:
select * from t_user where username = 'Alice' ;
这样在预编译之前的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#
java代码里:
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的排序字段作为变量时,使用${}。
你真的了解Mybatis的${}和#{}吗?是否了解应用场景?的更多相关文章
- 你真的了解MyBatis中${}和#{}的区别吗?
动态sql是mybatis的主要特性之一.在mapper中定义的参数传到xml中之后,在查询之前mybatis会对其进行动态解析. mybatis提供了两种支持动态sql的语法:#{} 和 ${}. ...
- Mybatis和Hibernate本质区别和应用场景
Hibernate:是一个标准ORM(对象关系映射)框架.入门门槛较高,不需要程序员写sql语句,sql语句自动生成,对sql语句优化.修改比较困难 应用场景:适用于需求变化不多的中小型项目,比如后台 ...
- mybatis 和 hibernate 本质区别和应用场景
Hibernate: 是一个标准 ORM 框架(对象关系映射).入门门槛较高,不需要程序员写 SQL,SQL语句自动生成. 对 SQL 语句进行优化.修改比较困难. 应用场景: 适用于需求变化不多的中 ...
- springMVC 接收数组参数,mybatis 接收数组参数,mybatis批量插入/批量删除案例
案例是给一个用户赋予多个权限,多个权限用其对应的主键 id 为参数,组成了 一个id数组,传给springMVC,然后springMVC传给mybatis,然后mybatis批量插入.其实类似的场景还 ...
- 一 mybatis快速入门
什么是MyBatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBatis可以使用简 ...
- mybatis 注解快速上手
一.mybatis 简单注解 关键注解词 : @Insert : 插入sql , 和xml insert sql语法完全一样 @Select : 查询sql, 和xml select sql语法完全一 ...
- mybatis系列-03-入门程序
3.1 需求 根据用户id(主键)查询用户信息 根据用户名称模糊查询用户信息 添加用户 删除 用户 更新用户 3.2 环境 java环境:jdk1.7.0_79 eclipse mys ...
- Spring+SpringMVC+MyBatis深入学习及搭建(一)——MyBatis的基础知识
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6812311.html 1.对原生态jdbc程序中问题总结 1.1 jdbc程序 需求:使用jdbc查询mys ...
- MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间
Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...
随机推荐
- Linux设备驱动程序学习----2.内核模块与应用程序的对比
内核模块与应用程序的对比 更多内容请参考Linux设备驱动程序学习----目录 1. 内核模块与应用程序的对比 内核模块和应用程序之间的不同之处: 大多数中小规模的应用程序是从头到尾执行单个任务,而模 ...
- 从零开发一款自己的小程序UI组件库(一)
写在前面:有开发过小程序的朋友肯定知道组件化开发的特性,高内聚与低耦合.使用已有的UI组件库,诸如:vantUI-weapp.minUI-weapp等UI组件库的诞生使我们的开发速度大大的加快,丰富的 ...
- 逆向MFC程序
目录 @ 1 MFC执行流程 1.1 环境支持 1.2 分析 1.3 实践探索 1.3.1 创建一个MFC程序 1.3.2 下关键断点并调试 1.4 转向MFC库源文件中观测 2 逆向 2.1 特征码 ...
- 基于V2EX API的nodejs组件.
今天又学习到了新的知(zi)识(shi),来给自己做个笔录,也算在这酷热的天气里给自己写了一篇降温的‘膏药’,话就讲这么多了 ,start off...... 首先 ,依赖选择: /**设置为严格模式 ...
- httpclient信任所有证书解决SSLException:Unrecognized SSL message,plaintext connection
在使用 HttpClient 工具调用第三方 Http 接口时报错 javax.net.ssl.SSLException:Unrecognized SSL message,plaintext conn ...
- 你可能不知道的Docker资源限制
What is 资源限制? 默认情况下,容器是没有资源限制的,它会尽可能地使用宿主机能够分配给它的资源.Docker提供了一种控制分配多少量的内存.CPU或阻塞I/O给一个容器的方式,即通过在dock ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
- Spring源码解析——循环依赖的解决方案
一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...
- Jenkins 配置 SpringBoot 自动构建部署
服务器版本 Linux version 3.10.0-957.12.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8 ...
- jenkins部署自动化项目备注
一.定时任务部署: 第一个*表示分钟,取值0~59 第二个*表示小时,取值0~23 第三个*表示一个月的第几天,取值1~31 第四个*表示第几月,取值1~12 第五个*表示一周中的第几天,取值0~7, ...