前言

​ 接触mybatis也是在今年步入社会之后,想想也半年多了,缺没时间去系统的学习,只知道大概,也是惭愧。

​ 不知道有多少刚毕业的同学和我一样,到现在还没仔仔细细去了解你每天都会见到使用到的框架呢?

​ 什么?你也不知道mybatis动态sql中${}和#{}的差异?其实我也是今天才知道的,我们一起来学习一下吧。

正文

不够刺激,再增加一点前戏

​ 在mybatis中,使用sql查询时,经常需要动态传递参数。大家往往会采用以下方式:

-- 以根据order_no 查询订单信息为例
-- ①
select * from order where order_no = #{orderNo}
-- ②
select * from order where order_no = '${orderNo}'

咦,不对!!!如果orderNo=’2017111695468435844135’,要最后执行后的结果与下面的语句执行结果一样,到底是用①还是②呢?

select * from order where order_no = '2017111695468435844135'

好吧。。。其实两种方式得到的结果是相同的。

but 在某些情况下,我们只能使用二者其一!!!


主题开始了


动态sql 是mybatis优于其他ORM框架的一个重要原因之一。

mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析,解析为一个BoundSql 对象,也是在此处对动态 SQL 进行处理的,使得#{}和${}在此处产生了差异。

#{}解析为一个JDBC中prepared statement的参数标记符

即:

select * from order where order_no = #{orderNo}

被解析为:

select * from order where order_no = ?

也即是,#{}被解析为一个参数占位符?.

${}则仅仅是一个纯粹的字符串替换

即:

select * from order where order_no = '${orderNo}' 

被解析为:

select * from order where order_no = '2017111695468435844135' 

也就是说,使用${}在预编译之前已经不包含变量name了,而#{}的变量替换是在DBMS中。

注意安全哦

  1. 能使用#{}的地方就别用${}.

    reason:1.使用#{},相同的预编译sql可以重复利用,性能比${}高;

    ​ 2. ${}在预编译之前已经被变量替换了,会存在sql注入问题。

​ 例如:

select * from ${tableName} where order_no = #{orderNo}

如果从客户端传入的tableName = “order;delete order; – “,那么sql动态解析之后,预编译之前的sql将变为:

select * from order;delete order; -- where order_no = #{orderNo}

– 之后的语句被注释了,然后,sql完全大变了。。。interesting!!!**

  1. 表名作为变量时,必须使用${}.表名是字符串,使用 sql 占位符替换字符串时会带上单引号 '',这会导致 sql 语法错误.

再简单讲讲sql预编译

定义:

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

为什么需要预编译

JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译

    1. 预编译阶段可以优化 sql 的执行。 
      预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。
    2. 预编译语句对象可以重复利用。 
      把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。

MyBatis动态sql之${}和#{}区别的更多相关文章

  1. mybatis动态sql #和$的区别

    $和#都支持动态sql:就是你传什么它就是什么 区别: 1.#可以防止sql注入在sql执行时显示 '?' 比$安全 SELECT * FROM table WHERE id = ? 2.在使用#传入 ...

  2. mybatis 动态sql和参数

    mybatis 动态sql 名词解析 OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性, ...

  3. MyBatis动态Sql 的使用

    Mapper.xml提示: 1:mapper包中新建一个文件:mybatis-3-mapper.dtd 2:在web app libraries/mybatis.jar/org.apache.ibat ...

  4. MyBatis从入门到精通(第4章):MyBatis动态SQL【if、choose 和 where、set、trim】

    (第4章):MyBatis动态SQL[if.choose 和 where.set.trim] MyBatis 的强大特性之一便是它的动态 SQL.MyBatis 3.4.6版本采用了功能强大的OGNL ...

  5. MyBatis 动态SQL(十二)

    动态条件查询 以下是我们数据库表 tb_user 的记录: 假设现在有一个需求,就是根据输入的用户年龄和性别,查询用户的记录信息.你可能会说,这太简单了,脑袋里立马蹦出如下的 SQL 语句: SELE ...

  6. mybatis动态sql以及分页

    1.mybatis动态sql 2.模糊查询 3.查询返回结果集的处理 4.分页查询 5.特殊字符处理 1.mybatis动态sql If.trim.foreach If 标签判断某一字段是否为空 &l ...

  7. mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...

  8. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法   动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...

  9. 自己动手实现mybatis动态sql

    发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客.本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧. 用过mybatis的人,估计 ...

随机推荐

  1. 不能安装64位office提示已安装32位的

    安装64位office办公软件的时候提示已经安装32位的office办公软件所以无法继续安装,但实际上之前安装的32位的office办公软件已经卸载了.问题现象截图如下: 从问题描述中,我们其实已经能 ...

  2. SQL 多行合并一行

    select stuff((select ',' + CONVERT(VARCHAR(50),id)+'' from tab_menu  group by id for xml  path('')), ...

  3. 题解——洛谷P3390 【模板】矩阵快速幂(矩阵乘法)

    模板题 留个档 #include <cstdio> #include <algorithm> #include <cstring> #define int long ...

  4. [ECharts] - ECharts使用中国地图

    格式1: https://www.cnblogs.com/luna666/p/9007263.html  (非官方) <!DOCTYPE html> <html lang=" ...

  5. HDU 5583 Kingdom of Black and White(暴力)

    http://acm.hdu.edu.cn/showproblem.php?pid=5583 题意: 给出一个01串,现在对这串进行分组,连续相同的就分为一组,如果该组内有x个数,那么就对答案贡献x* ...

  6. 浅谈循环中setTimeout执行顺序问题

    浅谈循环中setTimeout执行顺序问题 (下面有见解一二) 期望:开始输出一个0,然后每隔一秒依次输出1,2,3,4. for (var i = 0; i < 5; i++) { setTi ...

  7. JAVA基础之复识二

    JAVA语言 未经本人允许禁止转载或使用 基础知识:JAVA数据类型,运算符,流程控制等 注释: // 单行注释 /* 多行连续注释 ... */ /** 文档注释,该类型的注释会生成一个html文件 ...

  8. js,jq获取父,兄弟,子节点整理

    js获取节点 父: parentNode 获取已知节点的父节点. 子: childNodes; 得到全部子节点 children 得到全部子节点 firstChild 获得第一个子节点 lastChi ...

  9. Jdbc -Statement

    Java提供了 Statement.PreparedStatement 和 CallableStatement三种方式来执行查询语句: PreparedStatement是用于执行参数化查询 预编译s ...

  10. Mac 如何安装 chromedriver

    1.使用brew  命令 前提是要安装 brew 这里不做介绍 使用命令 brew install chromedriver 如上图出现错误,根据提示可以使用如下命令安装 brew cask inst ...