这篇文章主要介绍了Mabitis中的  #{}与   ${} 符号区别,需要的朋友可以参考下

  一、介绍

  mybatis 中使用 Mapper.xml里面的配置进行 sql 查询,经常需要动态传递参数,例如我们需要根据用户的姓名来筛选用户时,sql 如下:

select * from user where name = "Jack";

  上述 sql 中,我们希望 name 后的参数 "Jack" 是动态可变的,即不同的时刻根据不同的姓名来查询用户。在 Mapper.xml文件中使用如下的 sql 可以实现动态传递参数 name:

select * from user where name = #{name};  //#{}相当于占位符

  或者是:

 select * from user where name = ${name};


  二、$ 与 #

  1. 区别 :

  动态 SQL 是 mybatis 的强大特性之一,也是它优于其他 ORM 框架的一个重要原因。mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析,解析为一个 BoundSql 对象,也是在此处对动态 SQL 进行处理的。

  在动态 SQL 解析阶段, #{ } 和 ${ } 会有不同的表现。

  #{ }:解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。

  例如,Mapper.xml中如下的 sql 语句:

 select * from user where name = #{name};

  动态解析为:

 select * from user where name = ?;

  一个 #{ } 被解析为一个参数占位符 ? 。 

  而${ } 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换。

  例如,Mapper.xml中如下的 sql:

 select * from user where name = ${name};

  当我们传递的参数为 "Jack" 时,上述 sql 的解析为:

select * from user where name = "Jack";

  预编译之前的 SQL 语句已经不包含变量了,完全已经是常量数据了。

  综上所得, ${ } 变量的替换阶段是在动态 SQL 解析阶段,而 #{ }变量的替换是在 DBMS 中

  三、用法

  1、能使用 #{ } 的地方就用 #{ }

  首先这是为了性能考虑的,相同的预编译 sql 可以重复利用。其次,${ } 在预编译之前已经被变量替换了,这会存在 sql 注入问题。例如,如下的 sql:

select * from ${tableName} where name = #{name}

  假如,我们的参数 tableName 为 user; delete user; --,那么 SQL 动态解析阶段之后,预编译之前的 sql 将变为:

 select * from user; delete user; -- where name = ?;

 //-- 之后的语句将作为注释,不起作用,因此本来的一条查询语句偷偷的包含了一个删除表数据的 SQL。

  2. 表名作为变量时,必须使用 ${ }

  这是因为,表名是字符串,使用 sql 占位符替换字符串时会带上单引号 '',这会导致 sql 语法错误,例如:

select * from #{tableName} where name = #{name};

  预编译之后的sql 变为:

select * from ? where name = ?;

  假设我们传入的参数为 tableName = "user" , name = "Jack",那么在占位符进行变量替换后,sql 语句变为:

select * from 'user' where name='Jack';

  上述 sql 语句是存在语法错误的,表名不能加单引号 ''(注意,反引号 ``是可以的)。

  四、sql预编译

  1. 定义:

  sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。

  2. 为什么需要预编译

  JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译。预编译阶段可以优化 sql 的执行。预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。预编译语句对象可以重复利用。

  把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。mybatis 默认情况下,将对所有的 sql 进行预编译。

最新文章

  1. UWP开发之Mvvmlight实践三:简单MVVM实例开发(图文详解付代码)
  2. js 数组赋值问题 :值传递还是引用?
  3. [.net 面向对象编程基础] (2) 关于面向对象编程
  4. PaintCode调研
  5. 线程池的使用ExecutorService
  6. 李洪强-C语言关键字、标识符和注释
  7. DataGridView点击排序完成后如何禁止自动排序
  8. OpenGL超级宝典第5版&&GLSL法线变换
  9. C# ASP.NET FILEUPLOAD详解
  10. python-字典(第二篇(四):字典)
  11. Tomcat 优化和性能监测
  12. 重要:关于PPT转图片需要注意的问题
  13. 爬虫框架Scrapy 之(二) --- scrapy文件
  14. Ubuntu创建新用户的正确姿势
  15. 历届试题 买不到的数目-(dp)
  16. 谈谈Enter回车键提交表单那些事 回车搜索 enter搜索
  17. Learning to Rank:Point-wise、Pair-wise 和 List-wise区别
  18. nexus 手动更改 私服包
  19. 多线程---再次认识volatile,Synchronize,lock
  20. Hadoop集群时钟同步

热门文章

  1. centos 记录所有用户操作命令的脚本
  2. .netcore 3.1高性能微服务架构:封装调用外部服务的接口方法--HttpClient客户端思路分析
  3. 从零开始一个个人博客 by asp.net core and angular(三)
  4. WebStorm2018破解教程
  5. 【01】HTML_day01_02-认识HTML
  6. uniapp后台api设计(微信user表)
  7. TP6文档-邓士鹏
  8. CF1311E Construct the Binary Tree
  9. Eclipse部署项目,常见几个问题解决方案
  10. es的分布式架构原理是什么?