前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MyBatis动态传递参数的两种方式#{}和${}

MyBatis动态传递参数的两种方式#{}和${}

作者头像
bisal
发布2021-10-29 10:17:21
2.3K0
发布2021-10-29 10:17:21
举报

最近做的Java规范更新涉及到MyBatis映射配置文件中动态传递参数的两种方式#{}和${},两者的区别,

(1) #{}为参数占位符?,即SQL预编译。${}为字符串替换,即SQL拼接,可以理解为仅仅是个纯碎的string替换,在动态SQL解析阶段将会进行变量替换。

(2) #{}是“动态解析->预编译->执行”的过程。${}是“动态解析->编译->执行”的过程。

(3) #{}的变量替换是在DBMS中。${}的变量替换是在DBMS外。

(4) 变量替换后,#{}对应的变量自动加上引号。变量替换后,${}对应的变量不会加上引号。

例如给参数name传递一个值test,如果是#{name},则值为'test',

代码语言:javascript
复制
select id,name,age from student where name=#{name}

如果是${name},则值为test,

代码语言:javascript
复制
select id,name,age from student where name=${name}

(5) #{}能防止SQL注入。${}不能防止SQL注入。

默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以他为背景设置安全的值(例如?)。这样做很安全,很迅速,是首选做法,有时只是想直接在SQL语句中插入一个不改变的字符串。例如ORDER BY,可以这样来使用ORDER BY ${columnName},这里MyBatis不会修改或转义字符串。

但是要知道,接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此不应该允许用户输入这些字段,或者通常自行转义并检查。

ORDER BY通常比较特殊,例如根据前端传过来的字段排序,用了如下格式,

代码语言:javascript
复制
select XXXX from table order by #{column} #{desc}

但是排序没生效,查看日志,发现实际执行的SQL如下所示,排序未生效,

代码语言:javascript
复制
select XXXXX from table order by "column" "desc"

主要还是对MyBatis传参形式不了解,官方介绍,

43ad88a338eaf2345260345c62b1cb65.png
43ad88a338eaf2345260345c62b1cb65.png

P.S. https://mybatis.org/mybatis-3/sqlmap-xml.html#Parameters

原文如下,

By default, using the #{} syntax will cause MyBatis to generate PreparedStatement properties and set the values safely against the PreparedStatement parameters (e.g. ?). While this is safer, faster and almost always preferred, sometimes you just want to directly inject an unmodified string into the SQL Statement. For example, for ORDER BY, you might use something like this: @Select("select * from user where ${column} = #{value}") User findByColumn(@Param("column") String column, @Param("value") String value);

#{}相当于jdbc中的preparedstatement,进行了预编译,而${}直接是字符串本身,是有意设计成这样,方便拼接成动态SQL,但可能存在注入的问题。

另外一个场景,就是隐式转换,SQL Server碰到过传入的是varchar,字段类型是varchar,但是通过#{},传入的就成了nvarchar,例如,

代码语言:javascript
复制
select * from test where id = #{id};

导致隐式转换,此时有两种解决,

(1) 需要在jdbc的url配置中添加sendStringParameterAsUnicode=false;关闭unicode字符串的转换,

代码语言:javascript
复制
jdbc:sqlserver://x.x.x.x:1433;DatabaseName=test;sendStringParametersAsUnicode=false;

(2) #{}改为${},避免类型转换,

代码语言:javascript
复制
select * from test where id = '${id}';

因此,

(1) 能用#{}的地方就用#{},不用或少用${}。

(2) 表名作参数时,必须用{},例如select * from {tableName}。

(3) ORDER BY时,必须用${},例如,

代码语言:javascript
复制
select * from t_user order by ${columnName}

(4) 使用{}时,要注意何时加或不加单引号,即{}和'

(5) 存在隐式转换时,注意${}和#{}。

参考资料,

https://mybatis.org/mybatis-3/sqlmap-xml.html#Parameters

https://www.cnblogs.com/yang82/p/7813549.html

https://blog.csdn.net/siwuxie095/article/details/79190856

https://blog.csdn.net/angyuhh07719/article/details/102429418

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档