MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
动态 sql 是 mybatis 的主要特性之一,在mybatis中我们可以把参数传到xml文件,由mybatis对sql及其语法进行解析,mybatis支持使用${}和#{}。
那么${}
和#{}
有什么区别呢?
mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析。
#{}
#{}
是sql的参数占位符。#{}
相当于JDBC中的PreparedStatement,对于传入的参数,在预处理阶段使用 ?
代替,真正查询的时候即在数据库管理系统中(DBMS)才代入参数。
例如:
mapper.xml中的sql语句:
select * from user where name = #{name};
解析为:
select * from user where name = ?;
一个#{}
被解析为一个参数占位符 ?
,不管传入什么参数,打印的sql都是这样的。
执行时,直接使用编译好的SQL,替换占位符?
就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
${ }
${}
是properties文件中的变量占位符,仅仅为一个纯粹的String替换。
上面的例子传递参数为 “admin” 时,sql解析为
select * from user where name = "admin";
预编译之前的 SQL 语句已经不包含变量 name 了。
如果传递参数为 user;delet user;–,那么sql动态解析阶段之后,预编译之前的sql将变为
select * from user;delete user; -- where name = ?;
--
之后的语句将作为注释,不起作用,因此本来的一条查询语句偷偷的包含了一个删除表数据的 SQL!
总结
#{}是经过预编译的,是安全的;${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
sql预编译
-
定义
sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。 -
为什么需要预编译
JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译。
1)预编译阶段可以优化 sql 的执行。预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。
2)预编译语句对象可以重复利用。
把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。
mybatis 默认情况下,将对所有的 sql 进行预编译。
最后
以上就是烂漫猫咪最近收集整理的关于MyBatis中防止 sql注入及#{ }和${ }的区别的全部内容,更多相关MyBatis中防止内容请搜索靠谱客的其他文章。
发表评论 取消回复