当前位置: 移动技术网 > IT编程>数据库>Mysql > 你真的了解MyBatis中${}和#{}的区别吗?

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

2019年09月06日  | 移动技术网IT编程  | 我要评论

动态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
关注微信公众号【悟能之能】了解更多编程技巧。
回复"面经"获取面试资料

如对本文有疑问, 点击进行留言回复!!

相关文章:

  • mysql解决时区相关问题

    前言:在使用 mysql 的过程中,你可能会遇到时区相关问题,比如说时间显示错误、时区不是东八区、程序取得的时间和数据库存储的时间不一致等等问题。其实,这些问题... [阅读全文]
  • MySQL8.0内存相关参数总结

    mysql理论上使用的内存 = 全局共享内存 + max_connections×线程独享内存。也就是:innodb_buffer_pool_size + in... [阅读全文]
  • mysql如何查询日期与时间

    前言: 在项目开发中,一些业务表字段经常使用日期和时间类型,而且后续还会牵涉到这类字段的查询。关于日期及时间的查询等各类需求也很多,本篇文章简单讲讲日期及时间字... [阅读全文]
  • 深入了解mysql长事务

    前言: 本篇文章主要介绍mysql长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案。注意:本... [阅读全文]
  • 详解mysql DML语句的使用

    前言: 在上篇文章中,主要为大家介绍的是ddl语句的用法,可能细心的同学已经发现了。本篇文章将主要聚焦于dml语句,为大家讲解表数据相关操作。这里说明下ddl与... [阅读全文]
  • JDBC怎么连接数据库

    JDBC的快速入门(写这个东西是为了自己记一个笔记,或者为了方便别人应付作业)你要连接什么数据库就要下载什么类型... [阅读全文]
  • 高性能Mysql的逻辑架构和常见的存储引擎

    高性能Mysql的逻辑架构和常见的存储引擎

    前言: 为了充分发挥MySQL的性能并顺利地使用,就必须理解其设计。MySQL的灵活性体现在很多方面。例如,... [阅读全文]
  • 如何选择合适的MySQL日期时间类型来存储你的时间

    构建数据库写程序避免不了使用日期和时间,对于数据库来说,有多种日期时间字段可供选择,如 timestamp 和 datetime 以及使用 int 来存储 un... [阅读全文]
  • MySQL数据库使用规范总结

    导读: 关于mysql数据库规范,相信大家多少看过一些文档。本篇文章给大家详细分类总结了数据库相关规范,从库表命名设计规范讲起,到索引设计规范,后面又给出sql... [阅读全文]
  • 详解MySQL 外键约束

    官方文档:1.外键作用:mysql通过外键约束来保证表与表之间的数据的完整性和准确性。2.外键的使用条件 两个表必须是innodb表,myisam表暂时不支持... [阅读全文]
验证码:
移动技术网