【Mybatis系列】#{}和${}有什么区别?

  • 在我们开发过程中写mybatis的时候可能大多数人都使用的是#{} ,但是我们还有另外一个符号${},他们之间的区别是什么?

当我们在应用变量的时候默认使用#{},如下: 

<select id=getUserById  resultType="org.hyf.mybatis.model.User">
    select * from user where id = #{id};
</select>
<select id=getUserById  resultType="org.hyf.mybatis.model.User">
    select * from user where id = ${id};
</select>

通过上面的例子好像并没有看出他们之间有什么区别

一、下面我们通过日志来看一下他们之间的区别:

添加日志依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.5</version>
</dependency>

在resources目录下,添加log4j.properties 

log4j.rootLogger=DEBUG,stdout
log4j.logger.org.mybatis=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n 

先看通过${}运行的日志:

从上面的日志中可以看出,${}是一个纯粹的string 替换,在动态sql解析阶段会进行变量替换

sql直接拼接就好了,Parameters为空

看#{}运行的日志

 

解析为一个JDBC的预编译语句的参数标记符

#{}是占位符的方式来解决参数传递问题,变量的替换是在DBMS中,而且替换会自动加单引号   ‘’

${}是参数拼接的问题,变量的替换是在动态SQL解析阶段,但是参数拼接可能会存在sql注入的 

二、用法:

1.能用#{}的地方就用#{},因为${}存在sql注入非常的不安全,可能一条查询语句就能变成删表操作

 例如: 

select * from ${tableName} where name=#{name}
这个时候我们传递tableName 为 user;delete user; --
sql预编译之后变成:

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

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

   知道为什么吗?  这是由于如果我们使用#{}占位符传递的话会自动加上单引号‘’,但是${}不会自动加单引号

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

预编译之后变成

select * from ? where name = ?;

假设我们传入的tableName=user name="zhangsan"

select * from 'User' where name='zhangsan';

上述sql语句是错误的,表名不能加单引号

三、什么是sql预编译?

在上面的介绍中提到了很多次的sql预编译,sql预编译就是在数据库驱动在发送sql语句和参数给DBMS之前对sql语句进行编译,这样DBMS在执行sql语句就不需要重新编译

猜你喜欢

转载自blog.csdn.net/qq_30631063/article/details/108212978