转自: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的${}和#{}吗?是否了解应用场景?的更多相关文章

  1. 你真的了解MyBatis中${}和#{}的区别吗?

    动态sql是mybatis的主要特性之一.在mapper中定义的参数传到xml中之后,在查询之前mybatis会对其进行动态解析. mybatis提供了两种支持动态sql的语法:#{} 和 ${}. ...

  2. Mybatis和Hibernate本质区别和应用场景

    Hibernate:是一个标准ORM(对象关系映射)框架.入门门槛较高,不需要程序员写sql语句,sql语句自动生成,对sql语句优化.修改比较困难 应用场景:适用于需求变化不多的中小型项目,比如后台 ...

  3. mybatis 和 hibernate 本质区别和应用场景

    Hibernate: 是一个标准 ORM 框架(对象关系映射).入门门槛较高,不需要程序员写 SQL,SQL语句自动生成. 对 SQL 语句进行优化.修改比较困难. 应用场景: 适用于需求变化不多的中 ...

  4. springMVC 接收数组参数,mybatis 接收数组参数,mybatis批量插入/批量删除案例

    案例是给一个用户赋予多个权限,多个权限用其对应的主键 id 为参数,组成了 一个id数组,传给springMVC,然后springMVC传给mybatis,然后mybatis批量插入.其实类似的场景还 ...

  5. 一 mybatis快速入门

    什么是MyBatis MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索. MyBatis可以使用简 ...

  6. mybatis 注解快速上手

    一.mybatis 简单注解 关键注解词 : @Insert : 插入sql , 和xml insert sql语法完全一样 @Select : 查询sql, 和xml select sql语法完全一 ...

  7. mybatis系列-03-入门程序

    3.1     需求 根据用户id(主键)查询用户信息 根据用户名称模糊查询用户信息 添加用户 删除 用户 更新用户 3.2     环境 java环境:jdk1.7.0_79 eclipse mys ...

  8. Spring+SpringMVC+MyBatis深入学习及搭建(一)——MyBatis的基础知识

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6812311.html 1.对原生态jdbc程序中问题总结 1.1 jdbc程序 需求:使用jdbc查询mys ...

  9. MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间

    Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...

随机推荐

  1. C++ 过滤出字符串的中文(GBK,UTF-8)

    最近在处理游戏敏感词之类的东西,为了加强屏蔽处理,所以需要过滤掉字符串中的除汉字之外的是其他东西如数字,符号,英文字母等. 首先我查阅资料并写了个函数: 示例:返回输入字符串中汉字的个数: std:: ...

  2. Java匹马行天下之J2EE框架开发——Spring—>Spring框架知多少

    ————也许我注定成不了一个伟大的人,但是至少我可以做一个很棒的自己.我想我现在应该做的不是瞻前顾后,而是活在当下,正确认知自己,做好自己现在的工作,努力提升自己的能力,踏踏实实地做一个程序员 一.思 ...

  3. java并发编程(十)----JUC原子类介绍

    今天我们来看一下JUC包中的原子类,所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程),原子操作可以是 ...

  4. Amazon S3

    Amazon S3 是什么? Amazon S3 是亚马逊推出的一款存储服务,名为 Amazon Simple Storage Service,即亚马逊简单存储服务. 有些 S3 的概念需要了解一下: ...

  5. LeetCode——409. Longest Palindrome

    题目: Given a string which consists of lowercase or uppercase letters, find the length of the longest ...

  6. [android视频教程] 传智播客android开发视频教程

    本套视频共有67集,是传智播客3G-Android就业班前8天的的课程量.本套视频教程是黎活明老师在2011年底对传智播客原来的Android核心基础课程精心重新录制的,比早期的Android课程内容 ...

  7. Spring入门(九):运行时值注入

    Spring提供了2种方式在运行时注入值: 属性占位符(Property placeholder) Spring表达式语言(SpEL) 1. 属性占位符 1.1 注入外部的值 1.1.1 使用Envi ...

  8. Vector使用方法简单整理

    使用vector,需要引用vector库: #include<vector> 首先,创建一个可以容纳int的vector变量——arr: vector<int> arr; 接着 ...

  9. 扩展GroupBox控件

    1.GroupBox的边框颜色可以自行设置: 2.GroupBox可以设置边框的为圆角: 3.设置GroupBox标题在控件中的位置. 4.设置GroupBox标题的字体和颜色. 具体实现步骤Pane ...

  10. 【译】为什么要了解HTTP

    原文地址:Why should I care about HTTP? 原作信息:by Devon Campbell. Dec 15 '18 Originally published at raddev ...