当前位置: 首页 > news >正文

一些特殊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>

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

相关文章:

  • 小赢卡贷:聚焦为民金融业务,优化消费者服务体验
  • 卷积注意力模块 CBAM | CBAM: Convolutional Block Attention Module
  • idea中使用GlassFish服务器启动项目
  • Vscode——SSH连接不进去服务器的万能解决办法
  • 基于地图的平滑算法--佛洛依德路径平滑算法(FLOYD)
  • vue项目npm run build 打包之后如何在本地访问
  • vmware中Numlock和caplock一直闪烁(更新时间24/2/28)
  • 你知道什么是物联网MQTT么?
  • 机器学习-02-机器学习算法分类以及在各行各业的应用
  • Alist访问主页显示空白解决方法
  • xtu oj 1131 凹数
  • List去重有几种方式
  • rpcs3模拟器配置要求是什么?
  • paddleNLP 安装
  • 【算法笔记】位运算详解
  • 《设计模式》装饰者模式
  • SpringBoot--在Entity(DAO)中使用枚举类型
  • Session(服务端会话跟踪技术)
  • CVPR2022 BatchFormer
  • EXCEL中ADDRESS函数的使用
  • libtorch c++ 搭建分类网络进行训练和预测
  • 初学前端-JavaScript(语法)
  • Hold the door!protobuf从PC到STM32的互相通信
  • 【allegro 17.2软件操作保姆级教程一】软件操作环境设置
  • Python基础内容训练11(面向对象进阶)
  • 不要小看get post的区别
  • 32.(前端)主页布局
  • 【Python】9*9乘法口诀表(while、for两种循环)
  • React中组件通信有哪些方式
  • Redux简单使用
  • 【PyTorch深度学习项目实战100例】—— 基于Conv3D实现三维立体MNIST数据集分类 | 第54例
  • 当心!你的App 可能是山寨的