#{}和${}

总结:

#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防止sql注入,比较常用。

${}:先进行sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注入现象。只有在需要进行sql语句关键字拼接的情况下才会用到。

#{}的使用场景:

#{} 的工作机制:

MyBatis 会将 #{} 中的参数替换为 SQL 预编译语句 的占位符(即 ?),然后将参数通过 JDBC 预编译的方式传递给数据库。

Mapper 接口

public interface CarMapper {List<Car> selectByCarType(String carType);
}

XML 配置

<select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">selectid, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carTypefromt_carwherecar_type = #{carType}
</select>

Service 层调用

List<Car> cars = carMapper.selectByCarType("SUV");

在这里,"SUV" 这个参数会通过 MyBatis 的 #{} 绑定机制,替换到 SQL 语句中的占位符 ? 处,然后执行查询。

MyBatis 转换后的 SQL:

在 MyBatis 运行过程中,这段 SQL 会被转换成如下形式:

selectid, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
fromt_car
wherecar_type = ?

实际执行过程:

假设用户调用了如下 Java 代码:

List<Car> cars = carMapper.selectByCarType("SUV");

在实际执行时,JDBC 会生成如下的最终 SQL 语句,并将 "SUV" 参数绑定到 ? 占位符:

selectid, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
fromt_car
wherecar_type = 'SUV';

${}:

${} 的使用和 #{} 不同,它是直接拼接参数到 SQL 语句中,而不是作为 JDBC 预编译的占位符因此,${} 具有一定的风险(SQL 注入),但在某些场景下它仍然是有用的。

1. ${} 的工作原理

  • ${} 会将参数的值直接拼接到 SQL 语句中,在 SQL 执行前完成字符串替换。
  • 它不经过预编译,因此无法避免 SQL 注入风险。

示例:使用 ${} 拼接参数

<select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">selectid, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carTypefromt_carwherecar_type = ${carType}
</select>

如果 Java 代码中传入参数为 "SUV"

carMapper.selectByCarType("SUV");

执行的 SQL 语句会被拼接成:

selectid, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType
fromt_car
wherecar_type = SUV;

这条 SQL 会出错,因为它缺少引号来包裹字符串类型的值。根据 SQL 规范,SQL 语句中,字符串类型的值(如 "SUV")必须用 单引号 ' 包裹起来,否则会报语法错误。

如何解决报错?

加上单引号即可

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.powernode.mybatis.mapper.CarMapper"><select id="selectByCarType" resultType="com.powernode.mybatis.pojo.Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carwhere<!--car_type = #{carType}--><!--car_type = ${carType}-->car_type = '${carType}'</select>
</mapper>

${} 的适用场景 :

需求:通过向sql语句中注入asc或desc关键字,来完成数据的升序或降序排列。

CarMapper接口:

List<Car> selectAll(String ascOrDesc);

CarMapper.xml文件:

<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carorder by carNum #{key}
</select>

测试程序 

@Test
public void testSelectAll(){CarMapper mapper = (CarMapper) SqlSessionUtil.openSession().getMapper(CarMapper.class);List<Car> cars = mapper.selectAll("desc");cars.forEach(car -> System.out.println(car));
}

采用这种方式传值,最终sql语句会是这样:

select id,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carType 
from t_car order by carNum 'desc'

 desc是一个关键字,不能带单引号的,所以在进行sql语句关键字拼接的时候,必须使用${}!!

使用${} 改造  :

<select id="selectAll" resultType="com.powernode.mybatis.pojo.Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_car<!--order by carNum #{key}-->order by carNum ${key}
</select>

批量删除

需求:一次删除多条记录。

对应的sql语句:

  • delete from t_user where id = 1 or id = 2 or id = 3;

  • delete from t_user where id in(1, 2, 3);

 我们到底需要选择#{}还是${}呢?

正确选择应该是${},因为选择#{},sql语句会变成delete from t_user where id in('1,2,3')  执行错误:1292 - Truncated incorrect DOUBLE value: '1,2,3'

正确写法:

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

对应的接口:

/*** 根据id批量删除* @param ids* @return*/
int deleteBatch(String ids);

模糊查询:

查询奔驰系列的汽车。【只要品牌brand中含有奔驰两个字的都查询出来。】

使用${}

/*** 根据品牌进行模糊查询* @param likeBrank* @return*/
List<Car> selectLikeByBrand(String likeBrank);
<select id="selectLikeByBrand" resultType="Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carwherebrand like '%${brand}%'
</select>

对应的sql语句:

  selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carwherebrand like '%宝马%'
@Test
public void testSelectLikeByBrand(){CarMapper mapper = SqlSessionUtil.openSession().getMapper(CarMapper.class);List<Car> cars = mapper.selectLikeByBrand("奔驰");cars.forEach(car -> System.out.println(car));
}

使用#{}

第一种:concat函数
​
<select id="selectLikeByBrand" resultType="Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carwherebrand like concat('%',#{brand},'%')
</select>​
第二种:双引号方式(比较常用)
<select id="selectLikeByBrand" resultType="Car">selectid,car_num as carNum,brand,guide_price as guidePrice,produce_time as produceTime,car_type as carTypefromt_carwherebrand like "%"#{brand}"%"
</select>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pthread_create

pthread_create 是 POSIX 线程&#xff08;Pthreads&#xff09;库中的一个函数&#xff0c;用于创建一个新的线程。这个函数允许程序在运行时并发执行多个线程&#xff0c;从而提高程序的效率和响应能力。 函数原型 #include <pthread.h>int pthread_create(pthread_t…

【设计模式-我的思考】套餐模式

imom排故下线-订单状态集查询功能实现(套餐模式) 需求描述 排故下线状态 不排故&#xff1a;未启用排故下线确认配置&订单状态参数值&#xff01;&#xff08;170、180、190&#xff09; 待排故&#xff1a;启用排故下线确认配置&排故下线确认未执行&订单状态参数…

Spire.PDF for .NET【页面设置】演示:在 C# 中应用 PDF 页面转换

当您在导出为 PDF 格式的文档中翻页时&#xff0c;页面过渡会显示装饰效果&#xff0c;例如溶解或擦除。当您以 PDF 格式创建幻灯片时&#xff0c;页面过渡特别有用。Spire.PDF是一款专为开发人员设计的强大 .NET 组件&#xff0c;可让您将页面过渡应用于 PDF 文件。 这里介绍…

vue3学习记录-组件通信

vue3学习记录-组件通信 1.父子组件通信2.兄弟组件传值2.1 以父组件为媒介2.2 发布订阅模式2.3 使用mitt2.3.1 全局使用2.3.2 局部使用 1.父子组件通信 父组件&#xff1a; <template>父组件原有的title:{{ title }}<p>---</p><com :title"title&qu…

MyBatis入门之一对一关联关系(示例)

【图书介绍】《SpringSpring MVCMyBatis从零开始学&#xff08;视频教学版&#xff09;&#xff08;第3版&#xff09;》-CSDN博客 《SpringSpring MVCMyBatis从零开始学(视频教学版)&#xff08;第3版&#xff09;》(杨章伟&#xff0c;刘祥淼)【摘要 书评 试读】- 京东图书 …

RK3576 安卓SDK编译环境搭建

编译 Android14 对机器的配置要求较高: 建议预留500G存储 多分配CPU和内存 建议使用 Ubuntu 20.04 操作系统或更高版本 sudo apt-get updatesudo apt-get install git gnupg flex bison gperf libsdl1.2-dev \ libesd-java libwxgtk3.0-dev squashfs-tools build-essential …

软考-软件设计师(11)-专题强化-算法设计与分析-算法特性、算法表示、算法时间复杂度、算法分类、C语言程序设计

场景 以下为高频考点、知识点汇总。 软件设计师上午选择题知识点、高频考点、口诀记忆技巧、经典题型汇总: 软考-软件设计师(1)-计算机基础知识点:进制转换、数据编码、内存编址、串并联可靠性、海明校验码、吞吐率、多媒体等: 软考-软件设计师(1)-计算机基础知识点:进制…

FreeRTOS实时操作系统(1)

前言&#xff1a;FreeRTOS内容较多&#xff0c;分篇发布&#xff0c;较为基础&#xff0c;旨在梳理知识&#xff0c;适合入门的同学 &#xff08;基于正点原子STM32F103开发板V2&#xff09; &#xff08;对于本篇&#xff0c;若有疑问&#xff0c;欢迎在评论区留言&#…

Wooden UI(木头UI纹理按钮边框 背景图标 带PNG素材)

资源包包含以下元素&#xff1a;按钮、图标、框架、复选框等&#xff0c;提供分层的 PSD 文件。 下载&#xff1a;​​Unity资源商店链接资源下载链接 效果图&#xff1a;

橡皮鸭调试法(Rubber Duck Debugging)

橡皮鸭调试法&#xff08;Rubber Duck Debugging&#xff09;是一种编程中的调试技巧&#xff0c;名字来源于一本书《The Pragmatic Programmer》&#xff0c;其中提到程序员可以把问题讲给一只橡皮鸭听&#xff0c;以便在讲解的过程中梳理思路并找到问题的根源。 基本原理&am…

微服务基础架构(图)

微服务基础架构是一种现代化的软件架构模式&#xff0c;旨在将大型复杂的应用程序拆分为多个小型、独立的服务。每个微服务专注于特定的业务功能&#xff0c;可独立开发、部署和扩展。 在微服务基础架构中&#xff0c;通常会使用轻量级的通信机制&#xff0c;如 RESTful API 或…

RISC-V笔记——RVWMO基本体

1. 前言 RISC-V使用的内存模型是RVWMO(RISC-V Weak Memory Ordering)&#xff0c;它是Release Consistency的扩展&#xff0c;因此&#xff0c;RVWMO的基本特性类似于RC模型。 2. RC模型 Release consistency(RC)的提出是基于一个观察&#xff1a;将所有同步操作用FENCE围在一…

升级Unity后产生的Objects内存泄露现象

1&#xff09;升级Unity后产生的Objects内存泄露现象 2&#xff09;能否使用OnDemandRendering API来显示帧率 3&#xff09;Unity闪退问题 4&#xff09;配置表堆内存如何优化 这是第405篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&#xff0c;涵盖了UWA问答…

PHP 8.1.0-dev后门远程命令执行漏洞

#简介 PHP verion 8.1.0-dev于2021年3月28日与后门一起发布&#xff0c;但是后门很快被发现并删除。 #漏洞概述 PHP verion 8.1.0-dev的PHP在服务器上运行&#xff0c;则攻击者可以通过发送User-Agentt标头执行任意代码。 #影响版本 PHP 8.1.0-dev #环境搭建 新建docker…

CentOS 7 安装gcc编译环境

有时需要使用源码安装某个应用程序&#xff0c;有时还需要对源码进行一定程度的修改和定制才能满足业务需求&#xff0c;有时需要在linux环境下开发某个特定功能的c程序&#xff0c;此时都需要用到gcc编译环境&#xff0c;此时就需要安装gcc编译环境。 在 CentOS 7 上安装 C 编…

记一个mysql的坑

数据库表user&#xff0c; 存在一个name字段&#xff0c;字段为varchar类型 现在user表有这么两条记录: idnameageclass1NULL18一班2lisi20二班 假如我根据下面这一条件去更新&#xff0c;更新成功数据行显示为0 update user set age 19 where age 18 and class “一班”…

前端算法:字典and哈希表(力扣1题、349题解法)

目录 一、字典 1.概念 2.特点 3.在JS中如何实现 4.字典用法 使用对象作为字典 使用map 5.应用场景 二、哈希表 1.概念 2.工作原理 3. 在 JavaScript 中的实现 4.哈希表用法 使用 Map 作为哈希表 5.应用场景 三、字典与哈希表的区别 四、力扣算法实战 1.1题 两数…

LLM之RAG实战(四十四)| rag-chatbot:支持Huggingface和Ollama任意模型的多PDF本地RAG方案

特点&#xff1a; 支持本地运行和Kaggle (new)运行支持Huggingface 和Ollama 的任意模型Process multiple PDF inputs.Chat with multiples languages (Coming soon).Simple UI with Gradio. 一、安装使用 1.1 Kaggle&#xff08;推荐&#xff09; Step1&#xff1a;把https…

Android 10.0 Camera2 拍照镜像功能实现

1.前言 在10.0的系统rom定制化开发中,在进行camera2的相关拍照功能开发中,在某些时候会遇到拍照照片 左右镜像的问题,就是照片左半边和右半边是反的,所以就需要在拍照的时候保存图片的时候实现 左右镜像功能,接下来就来分析下拍照保存图片的流程 2.Camera2 拍照镜像功能实…

JDK17新特性,代码使用,作用详细讲解

目录 1.密封类和密封接口 作用 好处 1. 密封类 2. 密封接口 3. 非密封类 4. 抽象密封类 2.模式匹配for instanceof JDK17前的jdk版本 新JDK17 特性与优点 使用示例 注意事项 作用 3.文本块 作用 好处 代码实例 1. 基本语法&#xff1a; 2.换行和缩进&#xff1a; 3.包…