mybatis动态sql中#{}和${}的区别

  1. #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。#{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

  2. 表 示 拼 接 s q l 串 , 通 过 {}表示拼接sql串,通过 sql{}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换, 可 以 接 收 简 单 类 型 值 或 p o j o 属 性 值 , 如 果 p a r a m e t e r T y p e 传 输 单 个 简 单 类 型 值 , {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值, pojoparameterType{}括号中只能是value。

注: (1)简单类型就是不是自己定义的类型 (2)模糊查询:'%${value}%' 不可漏掉单引号

在动态sql解析过程,#{}与${}的效果是不一样的:

  • #{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符。

如以下sql语句
select * from user where name = #{name}; 会被解析为: select * from
user where name = ?; 可以看到#{}被解析为一个参数占位符?。

  • ${ } 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换

如以下sql语句: select * from user where name = ${name};
当我们传递参数“sprite”时,sql会解析为: select * from user where name = “sprite”;
可以看到预编译之前的sql语句已经不包含变量name了。

综上所得, ${ } 的变量的替换阶段是在动态 SQL 解析阶段,而 #{ }的变量的替换是在 DBMS 中。

#{}与${}的区别可以简单总结如下:
  • #{}将传入的参数当成一个字符串,会给传入的参数加一个双引号
  • ${}将传入的参数直接显示生成在sql中,不会添加引号
  • #{}能够很大程度上防止sql注入,${}无法防止sql注入

${}在预编译之前已经被变量替换了,这会存在sql注入的风险。如下sql

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

如果传入的参数tableName为user; delete user; --,那么sql动态解析之后,预编译之前的sql将变为:

select * from user; delete user; - - where name = ?;
· 注意: - -之后的语句将作为注释不起作用

顿时我和我的小伙伴惊呆了!!!看到没,本来的查询语句,竟然偷偷的包含了一个删除表数据的sql,是删除,删除,删除!!!重要的事情说三遍,可想而知,这个风险是有多大。

  • ${}一般用于传输数据库的表名、字段名等
  • 能用#{}的地方尽量别用${}

进入正题,通过上面的分析,相信大家可能已经对如何动态调用表名和字段名有些思路了。示例如下:

<select id="getUser" resultType="java.util.Map" 
     parameterType="java.lang.String" statementType="STATEMENT">
     
    select 
        ${columns}
    from ${tableName}
        where COMPANY_REMARK = ${company}
        
  </select>

要实现动态调用表名和字段名,就不能使用预编译了,需添statementType=“STATEMENT”" 。

statementType:STATEMENT(非预编译),PREPARED(预编译)或CALLABLE中的任意一个,这就告诉 MyBatis分别使用Statement,PreparedStatement或CallableStatement。默认:PREPARED。这里显然不能使用预编译,要改成非预编译。其次,sql里的变量取值是${xxx},不是#{xxx}。

因为 是 将 传 入 的 参 数 直 接 显 示 生 成 s q l , 如 {}是将传入的参数直接显示生成sql,如 sql{xxx}传入的参数为字符串数据,需在参数传入前加上引号,如:

String name = “sprite”;
name = “’” + name + “’”;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值