• Mybatis中#{}和${}的区别


        前几天去一家公司笔试,有一道题是“Mybatis中#{}和${}的区别?”。说实话,当时自己真的不是很清楚,因为我本人没有怎么学习过mybatis,虽然最近做的项目用的是mybatis,但也只涉及到最基本的增、删、改、查,多表之间的关联也几乎没有用到。而#{}只在mapper映射文件中用到,${}在JS和前端JSP页面中用到。后来上网查了一下发现,二者之间的区别还是很大的,现在把自己查到的资料归纳总结如下,便于大家讨论学习。

    一般说来,二者的区别可总结为以下6点:

    (1)#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111",如果传入的值是id,则解析成的sql为order by "id"。

    (2)$将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id。 

    (3)#方式在很大程度上能够防止sql注入。

    (4)$方式无法防止sql注入。

    (5)$方式一般用于传入数据库对象,例如传入表名。

    (6)一般能用#的就别用$。 

    ps:在使用mybatis中还遇到<![CDATA[]]>的用法,在该符号内的语句,将不会被当成字符串来处理,而是直接当成sql语句,比如要执行一个存储过程。

    实例讲解:

          动态 sql 是 mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}。

    在下面的语句中,如果 name 的值为 zhangsan,则两种方式无任何区别:

    select * from user where name = #{name};
    select * from user where name = ${name};

      其解析之后的结果均为

    select * from user where name = 'zhangsan';

          但是 #{} 和 ${} 在预编译中的处理是不一样的。#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 sql 语句:

    select * from user where name = ?;

      而 ${} 则只是简单的字符串替换,在动态解析阶段,该 sql 语句会被解析成

    select * from user where name = 'zhangsan';

      以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

      那么,在使用过程中我们应该使用哪种方式呢?

      答案是:优先使用 #{}。因为 ${} 会导致 sql 注入的问题。

    看下面的例子: 

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

      在这个例子中,如果表名为

       user; delete user; -- 

      则动态解析之后 sql 如下:

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

      --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。

      但是表名用参数传递进来的时候,只能使用 ${} 。这也提醒我们在这种用法中要小心sql注入的问题。

  • 相关阅读:
    TongJI Online Judge预赛(3): Game
    堆栈小应用:配对
    在.net中使用Udp协议创建简单的聊天程序
    TongJI Online Judge预赛(2): LOVE LETTER
    全排列问题之递归求解
    如何打造RSS阅读器
    Html 常用标志总结
    实现页面的分帧显示
    每天OnlineJudge之 “数素数”
    文本编辑器中,如何设计 撤销/重复栈
  • 原文地址:https://www.cnblogs.com/sushu-yaya/p/6962251.html
Copyright © 2020-2023  润新知