zoukankan      html  css  js  c++  java
  • mybatis中#{}和${}的区别

    mybatis中#{}和${}的区别

    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.一般能用#的就别用$.

    MyBatis排序时使用order by 动态参数时需要注意,用$而不是#

    1、#{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号,如上面的值 “4,44,514”就会变成“ '4,44,514' ”;

    2、${ }是字符串替换, MyBatis在处理${ }时,它会将sql中的${ }替换为变量的值,传入的数据不会加两边加上单引号。

    注意:使用${ }会导致sql注入,不利于系统的安全性!

    SQL注入:就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。常见的有匿名登录(在登录框输入恶意的字符串)、借助异常获取数据库信息等

    应用场合:

    1、#{ }:主要用户获取DAO中的参数数据,在映射文件的SQL语句中出现#{}表达式,底层会创建预编译的SQL;

    2、${ }:主要用于获取配置文件数据,DAO接口中的参数信息,当$出现在映射文件的SQL语句中时创建的不是预编译的SQL,而是字符串的拼接,有可能会导致SQL注入问题.所以一般使用$接收dao参数时,这些参数一般是字段名,表名等,例如order by {column}。

    注:

    ${}获取DAO参数数据时,参数必须使用@param注解进行修饰或者使用下标或者参数#{param1}形式;

    #{}获取DAO参数数据时,假如参数个数多于一个可有选择的使用@param。

    mybatis接口mapper文件中引用传入的参数是通过#{param}或者${param}来使用的。

    1.数据类型匹配

    #:会进行预编译,而且进行类型匹配

    $:不进行数据类型匹配

    2.实现方式

    #:用于变量替换

    $:实质上是字符串拼接

    3.#和$的使用场景

    1)变量的传递,必须使用#,使用#{}就等于使用了PrepareStatement这种占位符的形式,提高效率。可以防止sql注入等等问题。#方式一般用于传入添加,修改的值或查询,删除的where条件 id值

    select * from t_user where name = #{param}

    (2)$只是只是简单的字符串拼接,要特别小心sql注入问题,对应非变量部分,只能用$。$方式一般用于传入数据库对象,比如这种group by 字段 ,order by 字段,表名,字段名等没法使用占位符的就需要使用${}

    select count(*), from t_user group by ${param}

    3)能同时使用#和$的时候,最好用#。

    sql注入问题:

    SQL注入就是将原本的SQL语句的逻辑结构改变,使得SQL语句的执行结果和原本开发者的意图不一样.

    比如:使用Statement语句执行者,执行sql,会造成sql注入的问题,

    String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";

    如果我们把[' or '1' = '1]作为varpasswd传入进来,执行查询的时候 sql会变成,

    String sql = "select * from tb_name where name= '' and passwd = '' or '1' = '1',1=1是永远成立的,所以,前面的条件已经不起作用,

    我们使用预编译语句执行者就可以避免这个问题,prepareStatement将sql预编译,传参数的时候,不会改变sql语句结构,就可以避免注入。

    纵有白头俱老意,奈何缘浅路芊芊.
  • 相关阅读:
    从零开始入门 K8s | 应用编排与管理
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    203. Remove Linked List Elements
    183. Customers Who Never Order
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    1261. Find Elements in a Contaminated Binary Tree
    1260. Shift 2D Grid
  • 原文地址:https://www.cnblogs.com/hanby/p/14172154.html
Copyright © 2011-2022 走看看