logo头像

Always believe youself.

Mybatis#和$的区别是什么?

‘#’ 与 ‘$’区别:

#{ }是预编译处理,$ { }是字符串替换。

  1. MyBatis在处理 #{ }时,会将SQL中的 #{ } 替换为?号,使用PreparedStatement的set方法来赋值;

  2. MyBatis在处理 ${ } 时,就是把 ${ } 替换成变量的值。

  3. 使用 #{ } 可以有效的防止SQL注入,更安全,更迅速,通常也是首选做法。

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

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

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

要理解记忆这个题目:

  • $ 符号一般用来当作占位符,常使用Linux脚本的同学应该对此有更深的体会吧。既然是占位符,当然就是被用来替换的。知道了这点就能很容易区分$和#,从而不容易记错了。
  • 预编译的机制。预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。
  • SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。
  • 在某些特殊场合下只能用${},不能用#{}。例如:在使用排序时ORDER BY ${id},如果使用#{id},则会被解析成ORDER BY “id”,这显然是一种错误的写法。

防止sql注入的几种方式(可能不止这几种):

  • jdbc使用 PreparedStatement代替Statement, PreparedStatement 不仅提高了代码的可读性和可维护性.而且也提高了安全性,有效防止sql注入;
  • 在程序代码中使用正则表达式过滤参数。使用正则表达式过滤可能造成注入的符号,如’ –等
  • 在页面输入参数时也进行字符串检测和提交时进行参数检查,同样可以使用正则表达式,不允许特殊符号出现。

sql预编译

定义

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

为什么需要预编译

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

  • 预编译阶段可以优化 sql 的执行。

预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。

  • 预编译语句对象可以重复利用。

把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。

mybatis sql 动态解析

mybatis 在调用 connection 进行 sql 预编译之前,会对sql语句进行动态解析,动态解析主要包含如下的功能:

  • 占位符的处理

  • 动态sql的处理

  • 参数类型校验