一些特殊SQL使用Mybatis的#{}和${}注意点

Mybatis对JDBC进行了进一步封装,使得我们可以更加便捷的使用Java操作数据库。Mybatis获取参数值有两种方式:#{}${}

在大部分情况下,#{}${}都能相互替代,使用两者之一即可,更加推荐使用#{},因为可以防止SQL注入问题,但是由于#{}${}本质上的不同,部分SQL语句使用#{}${}需要格外注意

#{}和${}本质区别

  1. #{}本质上是占位符赋值,为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号
  2. ${}本质上是字符串拼接,为字符串类型或日期类型的字段进行赋值时,需要手动加单引号

模糊查询

这个场景下,使用#{}${}都能达到目的,但是用法稍有不同

Mapper接口

List<User> selectLike(@Param("likeString") String likeString);

直接使用#{}

<select id="selectLike" resultType="pojo.User">
	select * from user where user_name like '%#{likeString}%'
</select>

结果报错,?占位符被当做字符串处理了

在这里插入图片描述

将#{}换成${}

<select id="selectLike" resultType="pojo.User">
    select * from user where user_name like '%${likeString}%'
</select>

成功执行

如果非要使用#{},也不是没有解决办法

使用""拼接

<select id="selectLike" resultType="pojo.User">
    select * from user where user_name like "%"#{likeString}"%"
</select>

结果
在这里插入图片描述

使用concat函数

<select id="selectLike" resultType="pojo.User">
    select * from user where user_name like concat('%',#{likeString},'%')
</select>

结果

在这里插入图片描述

动态表名

在某些场景下,我们需要来回操作各种表,但SQL语句功能一致,这时我们可以使用动态表名,即传参为表名类型,这时就要从#{}${}中进行选择了

Mapper接口

List<User> selectAllFromTable(@Param("tableName") String tableName);

直接使用#{}

<select id="selectAllFromTable" resultType="pojo.User">
    select * from #{tableName}
</select>

结果报错,原因在于#{}为占位符赋值,传参为String的话就会自动补上单引号'',而表名不允许添加单引号,所以导致出错

在这里插入图片描述

使用${}

<select id="selectAllFromTable" resultType="pojo.User">
    select * from ${tableName}
</select>

结果成功了,所以在动态表名的情况下,我们只能使用${}

在这里插入图片描述

分页

分页是一个实际开发中用的很广泛的一个功能,但是使用MyBatis传参进行手动分页时,坑可不小

首先我们来看一下分页公式

select * from <表名> limit <每页大小> * (<页码> - 1), <每页大小>; 

写出公式,分页就变得很简单了,但是这时候使用#{}进行传参就有一些问题

/**
 * @param pageSize 每页大小
 * @param currentPage 当前页码
 * @return 结果集List
 */
List<User> selectAllByPage(@Param("pageSize") Integer pageSize, @Param("currentPage") Integer currentPage);

使用#{}

<select id="selectAllByPage" resultType="pojo.User">
    select * from #{pageSize} * (#{currentPage} - 1), #{pageSize}
</select>

结果报错,原因在于limit后面不能运算,而我们传入的正是运算表达式

在这里插入图片描述

既然不能运算,那我们将运算结果传进去不就好了?

<select id="selectAllByPage" resultType="pojo.User">
    select * from #{pageSize * (currentPage - 1)}, #{pageSize}
</select>

结果还是报错,原因在于#{}会将大括号内的表达式整体当成一个参数给占位符赋值,这显然是不可以的

在这里插入图片描述

使用${}

<select id="selectAllByPage" resultType="pojo.User">
    select * from user limit ${pageSize * (currentPage - 1)}, #{pageSize}
</select>

结果成功了,${}会先把大括号内的表达式计算出来,再来进行字符串拼接

在这里插入图片描述

注:不光分页场景需要注意${}和#{},其他需要传入计算表达式的场景也需要注意

批量删除

有些场景,需要我们根据id数组批量删除记录,这个时候也有一些坑

由于id数组的长度是不确定的,所以我们不能确定参数的个数,但是我们可以使用in关键字,这个时候我们将id数组转为字符串进行传参就好了

[1,2,3] => 1,2,3

Mapper接口

Integer deleteByIds(String Ids);

使用#{}

<delete id="deleteByIds">
    delete from user where id in (#{ids})
</delete>

结果报错,原因在于in后面的小括号里面的'1,2,3'为字符串类型且为一个整体,与整数类型不符,因此不能使用#{}

在这里插入图片描述

使用${}

<delete id="deleteByIds">
    delete from user where id in (${ids})
</delete>

结果成功了,看来有些场景不得不使用${}

在这里插入图片描述

使用${}

<delete id="deleteByIds">
    delete from user where id in (${ids})
</delete>

结果成功了,看来有些场景不得不使用${}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis中,#{}和${}是两种不同的占位符使用方式。 #{}用于传递参数,它会将传递的参数值安全地替换到SQL语句中,以防止SQL注入攻击。在SQL执行过程中,#{}会将参数值进行预编译处理,生成一个占位符,并使用PreparedStatement对象来执行SQL语句,这样可以提高执行效率。因此,#{}在编写动态SQL时是更安全和推荐的方式。 ${}则是直接将参数值拼接到SQL语句中,没有经过预编译处理。这种方式适用于一些特殊情况,比如在表名、列名等需要动态拼接的地方。但是,由于没有预编译处理,可能存在SQL注入的风险,所以在使用${}时需要特别小心,确保传递的参数是可信的。 综上所述,#{}和${}的使用场景可以总结如下: - 使用#{}时,适用于传递参数的情况,可以提高SQL执行效率,并且避免SQL注入攻击。 - 使用${}时,适用于一些需要动态拼接的场景,但需要注意防止SQL注入,确保传递的参数是可信的。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Mybatis #和$获取参数值的区别以及@param的使用场景](https://blog.csdn.net/Tom098/article/details/103381901)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Mybatis中#和$的区别](https://blog.csdn.net/m0_52388979/article/details/125720091)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值