美文网首页
Mybatis中#{}和${}区别以及预编译理解

Mybatis中#{}和${}区别以及预编译理解

作者: 打不开的回忆 | 来源:发表于2018-06-04 22:21 被阅读0次

开发中经常使用mybatis的orm框架对数据库进行相关操作,mybatis最大的好处就是可以使用动态sql,即在mybatis对sql进行预编译之前会对sql语句进行动态解析,处理之后再进行预编译从而到达DBMS执行sql语句。而我们开发中经常用到的动态传参#{param}和${param}在动态解析时会有可能产生不同的sql语句,下面我们就来讨论一下如何正确使用#和$。

预编译

先来熟悉一下预编译,所谓预编译理解下来即:数据库驱动在发送sql和参数到DBMS(数据库管理软件,暂时这么理解吧)之前,先对sql语句进行编译处理,之后DBMS则可以直接对sql进行处理,不需要再次编译,提高了性能。这一点mybatis 默认情况下,将对所有的 sql 进行预编译处理。

使用预编译可以带来哪些好处?

JDBC中使用PreparedStatement来抽象预编译语句,从而使用达到预编译效果。
1:预编译阶段可以对sql语句进行优化。   
    预编译可以将多个操作步骤合并成一个步骤,一般而言,越复杂的sql,编译程度也会复杂,难度大,耗时,费性能,而预编译可以合并这些操作,预编译之后DBMS可以省去编译直接运行sql。
2:预编译语句可以重复利用。
    把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。有兴趣的可以查看mysql驱动包里面的ConnectionImpl类是如何操作预编译的,这里提一下缓存PreparedStatement,在执行预编译时会先去判断是否存在缓存,如果存在则对参数清空,绑定新的参数。如果不存在则调用数据库进行预编译处理生成一个PreparedStatement对象。

mybatis动态解析

关于动态解析的原理,可以参考这篇文章,写的非常详细mybatis动态解析原理
理解下来当我们在xml文件中写入动态sql之后,调用相关封装类进行解析处理,最终生成一个BounSql,该类包括sql语句,参数,参数源数据等参数。

#{}和${}在动态解析时的区别?

mybatis动态解析时,对于变量的值替换发生在不同阶段。
#{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,变量替换完成在DBMS中。

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

这里需要说明的是并不是使用${}一定会产生注入,或是一定会被显示替换变量。

例如当${}使用在字段的动态变量时,mybatis在动态解析时是会替换成一个string字符串的,不是显示的字段名字。select * from user where name = ${name};传入name为auth,则在动态解析时也会生成select * from user where name = 'auth';从而DBMS进行处理sql。这里${}和#{}可以达到相同的效果,区别就是#{}会生成一个预编译sql给DBMS,在DBMS完成变量的替换。
然而如果${}的位置发生在from后面或是order by(开发中经常会用到动态根据字段排序),这时候会显式的使用变量;select * from user where name='auth' order by ${column};select * from ${tableName} where name=#{name};这类的${}会进行显式处理,即传入什么直接替换,例如${column}=id和${column}='id'则会产生不同的效果。而此类语句有可能会产生sql的注入,经典的例子:select * from ${tableName} where name = #{name};传入变量tableName= "user;delete user;-- " 动态解析后的sql:select *fromuser;deleteuser;-- where name = ?;会存在注入。如果select * from #{tableName} where name = #{name};传入tableName="user" 则产生无法编译的sql错误。

结论:能使用#{}尽量使用,因为i#{}可以产生一个预编译对象,可以重复利用,不会产生sql注入,当语句必须使用表明或者字段名时,需要排除sql注入的可能,必须使用${}。

相关文章

  • Mybatis中#{}和${}区别以及预编译理解

    开发中经常使用mybatis的orm框架对数据库进行相关操作,mybatis最大的好处就是可以使用动态sql,即在...

  • 2021-01-31今日主题: MyBatis

    今日主题: MyBatis MyBatis 中 #{}和 ${}的区别是什么? #{}是预编译处理,${}是字符替...

  • 【5分钟背八股】mybatis中#{}和${}的区别?

    mybatis中#{}和${}的区别是什么? a、#{}是预编译处理,${}是字符串替换。 b、Mybatis 在...

  • 13Mybatis

    1.mybatis 中 #{}和 ${}的区别是什么? {}是预编译处理,${}是字符串替换; Mybatis在处...

  • Java面试题(Mybatis)

    125.mybatis 中 #{}和 ${}的区别是什么? {}是预编译处理,KaTeX parse error:...

  • MyBatis基础面试题

    1、Mybatis 中 #{}和 ${}的区别是什么? 1)#{}是预编译处理,${}是字符串替换;2)#{}将传...

  • Mybatis

    mybatis中#和$的区别 $直接与SQL语句进行拼接,#以字符串进行拼接,即加“”; #{}会经过预编译, ...

  • Mybatis总结

    #{}和${}区别 #{}是预编译,mybatis处理#{}时,会将它替换成?,调用preparedStateme...

  • Mybatis之#{}和${}区别

    #{}和${}的区别 #{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。 Mybatis在处...

  • MyBatis中#和$的区别

    区别 #{ }是预编译处理,MyBatis在处理#{ }时,会将sql中的#{ }替换为?,然后调用Prepare...

网友评论

      本文标题:Mybatis中#{}和${}区别以及预编译理解

      本文链接:https://www.haomeiwen.com/subject/lefusftx.html