【JavaEE进阶】 #{}和${}

文章目录

  • 🍃前言
  • 🌳#{}和${}使⽤
    • 🚩Interger类型的参数(基础数据类型)
      • 🎈使用#{}
      • 🎈使用${}
    • 🚩String类型的参数
      • 使用🎈#{}
      • 使用🎈${}
  • 🎍#{}和${}区别
    • 🚩#{}性能更⾼
    • 🚩#{}更安全(防⽌SQL注⼊)
    • 🚩${}的使⽤场景
      • 🎈排序功能
      • 🎈like查询
  • 🍀#{}和${}区别总结
  • ⭕总结

🍃前言

MyBatis参数赋值有两种⽅式,使⽤ #{} 和 ${}进⾏赋值,接下来我们看下⼆者的区别

🌳#{}和${}使⽤

我们先来看一下两者在基础数据类型与string类型下的使用

🚩Interger类型的参数(基础数据类型)

🎈使用#{}

@Select("select * from userinfo where id= #{id}")
List<UserInfo> selectId(Integer id);

我们观察一下我们的打印日志:

在这里插入图片描述

发现我们输出的SQL语句:

select * from userinfo where id= ?

我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位.这种SQL我们称之为"预编译SQL"

🎈使用${}

@Select("select * from userinfo where id= ${id}")
List<UserInfo> selectId1(Integer id);

在这里插入图片描述
可以看到,这次的参数是直接拼接在SQL语句中了.

🚩String类型的参数

使用🎈#{}

@Select("select * from userinfo where username = #{name}")
List<UserInfo> selectId2(String name);

观察打印日志
在这里插入图片描述
结果与上面一样成功返回

使用🎈${}

再使用一下${}

@Select("select * from userinfo where username = #{name}")
List<UserInfo> selectId3(String name);

再次进行打印日志:

在这里插入图片描述

可以看到,这次的参数依然是直接拼接在SQL语句中了,但是字符串作为参数时,需要添加引号 ‘’ ,使⽤ ${} 不会拼接引号 ‘’ ,导致程序报错.

修改代码如下:

@Select("select * from userinfo where username = '${name}'")
List<UserInfo> selectId3(String name);

再次运行
在这里插入图片描述
结果实现正常

从上⾯两个例⼦可以简单看出:

#{} 使⽤的是预编译SQL,通过 ? 占位的⽅式,提前对SQL进⾏编译,然后把参数填充到SQL语句中.

#{} 会根据参数类型,⾃动拼接引号 ‘’ .${} 会直接进⾏字符替换,⼀起对SQL进⾏编译.如果参数为字符串,需要加上引号 ’ ’

参数为数字类型时,也可以加上,查询结果不变,但是可能会导致索引失效,性能下降

🎍#{}和${}区别

#{}和${}的区别就是预编译SQL即时SQL的区别.

🚩#{}性能更⾼

绝⼤多数情况下,某⼀条SQL语句可能会被反复调⽤执⾏,或者每次执⾏的时候只有个别的值不同(⽐如select的where⼦句值同,update的set⼦句值不同,insert的values值不同).

如果每次都需要经过上⾯的语法解析,SQL优化、SQL编译等,则效率就明显不⾏了.

在这里插入图片描述

预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率

🚩#{}更安全(防⽌SQL注⼊)

SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法

原因:由于没有对⽤⼾输⼊进⾏充分检查,⽽SQL⼜是拼接⽽成,在⽤⼾输⼊参数时,在参数中添加⼀些SQL关键字,达到改变SQL运⾏结果的⽬的,完成恶意攻击

接下来我们先看一个sql注入的例子:

注入sql代码: ’ or 1='1

首先我们有以下代码:

@Select("select * from userinfo where username = '${name}'")
List<UserInfo> selectId4(String name);

当我们正常传参数时,代码如下:

@Test
void selectId4() {List<UserInfo> list = assignmentMapper.selectId3("陈平安");System.out.println(list);
}

正常运行结果如下:
在这里插入图片描述
接下来我们注入sql代码如下:

@Test
void selectId4() {List<UserInfo> list = assignmentMapper.selectId3("' or 1='1 ");System.out.println(list);
}

再次运行:结果依然被正确查询出来了,其中参数or被当做了SQL语句的⼀部分
在这里插入图片描述
但是呢,我们需要查询的应该是一个人的信息,这里却将所有人的信息给打印了出来。

🚩${}的使⽤场景

从上⾯的例⼦中,可以得出结论:$ {}会有SQL注⼊的⻛险,所以我们尽量使⽤#{}完成查询

既然如此,是不是$ { }就没有存在的必要性了呢?

当然不是.接下来我们看下${}的使⽤场景

🎈排序功能

接下来我们来实现通过传递参数让表实现升序降序排序:

我们先用#{}

@Select("select * from userinfo order by id #{sort}")
List<UserInfo> selectId5(String sort);

当我们进行传参:

@Test
void selectId5() {List<UserInfo> list = assignmentMapper.selectId5("asc");System.out.println(list);
}

进行启动:
在这里插入图片描述
可以发现,当使⽤ #{sort} 查询时,asc前后⾃动给加了引号,导致sql错误

使用${}就可以避免这种情况:
在这里插入图片描述
除了这个之外,还有表名作为参数时,也只能使⽤ ${}

🎈like查询

同样,like使⽤#{}报错

@Select("select * from userinfo where username = like '%#{key}%' ")
List<UserInfo> selectId7(String key);

把#{}改成$ {}可以正确查出来,但是$ {}存在SQL注⼊的问题,所以不能直接使⽤${}

@Select("select * from userinfo where username = like concat('%',#{key},'%') ")
List<UserInfo> selectId7(String key);

🍀#{}和${}区别总结

  1. #{}:预编译处理,${}:字符直接替换

  2. #{}可以防⽌SQL注⼊,${}存在SQL注⼊的⻛险,查询语句中,可以使⽤#{},推荐使⽤#{}

  3. 但是⼀些场景,#{}不能完成,⽐如排序功能,表名,字段名作为参数时,这些情况需要使⽤${}

  4. 模糊查询虽然${}可以完成,但因为存在SQL注⼊的问题,所以通常使⽤mysql内置函数concat来完成

⭕总结

关于《【JavaEE进阶】 #{}和${}》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

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

相关文章

C++:引用

目录 概念&#xff1a; 引用的使用格式&#xff1a; 引用特性&#xff1a; 常引用 使用场景&#xff1a; 1、做参数 二级指针时的取别名 一级指针取别名 一般函数取别名 2、做返回值 函数返回值的原理&#xff1a; 引用的返回值使用&#xff1a; 引用和指针的对比&…

Java Swing桌面项目打包成可执行jar

前言 最近有需求&#xff0c;将Swing项目打包为一个可执行的jar包&#xff0c;遇见了一些问题&#xff0c;参考AI助手&#xff0c;解决了遇到的问题&#xff0c;也有一些亲身实践体会&#xff0c;记录一下。开发环境IntelliJ IDEA&#xff0c;JDK8&#xff0c;用kotlin语言实现…

navicat连接postgresql、人大金仓等数据库报错

navicat连接postgresql、人大金仓数据库报错问题是一个偶现的问题&#xff0c;需要我们特别关注&#xff1a; 1、客户端连接人大金仓数据库 这里注意&#xff1a;navicat连接postgresql、人大金仓数据库时均选择postgresql类型&#xff0c;因为人大金仓数据库底层和psql数据库…

【第五天】蓝桥杯备战

1、金币 https://www.lanqiao.cn/problems/357/learning/ 解法&#xff1a;暴力 import java.util.Scanner; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args) {Scanner scan new Scanner(System.in);//在此输入…

01_Anaconda环境搭建

概述 Anaconda包含了许多常用的科学计算和数据分析的库和工具。通过Anaconda&#xff0c;用户可以更方便地安装、管理和更新这些库和工具&#xff0c;从而提高工作效率。 Anaconda还提供了一个名为conda的包管理器&#xff0c;可以帮助用户方便地安装、管理和更新这些库和工具…

写静态页面——魅族声学_前端页面练习

1、效果: 1、html代码: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>魅族声学</titl…

金智易表通构建学生缴费数据查询+帆软构建缴费大数据报表并整合到微服务

使用金智易表通挂接外部数据,快速建设查询类服务,本次构建学生欠费数据查询,共有3块设计,规划如下: 1、欠费明细查询:学校领导和财务处等部门可查询全校欠费学生明细数据;各二级学院教职工可查询本二级学院欠费学生明细数据。 2、大数据统计报表:从应收总额、欠费总额…

Spring与Redis集成

1.引入RedisTemplate 据以前的情况&#xff0c;我们在Java中使用Redis时一般是使用Jedis来操作的&#xff0c;大致的一段代码如下所示 Overridepublic User findUserById(Integer id) {User user null;Jedis jedis null;try {jedis jedisPool.getResource();String userStr…

直接在GitHub上使用vscode阅读源码

方法&#xff1a; 直接在github后面输入1s即可 效果&#xff1a;

光学系统的核心--分辨率

前言 在机器视觉领域&#xff0c;可以把各个部件划分为光源&#xff0c;镜头&#xff0c;相机&#xff0c;采集卡&#xff0c;算法&#xff0c;运动平台等。各个部件都是系统的有机组合&#xff0c;均有各自的重要性。在实际应用中&#xff0c;成像镜头涉及的光学理论较多&…

[数据结构]-哈希

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习目标&…

智能工厂4G无线设备预测维护云端联动的DI、AI、DO混合信号处理单元

在现代工业智能化进程中&#xff0c;一款集成了丰富I/O接口并能与各大云平台无缝对接的智能设备显得尤为重要。比如最近推出的这款创新产品&#xff0c;它集合了8路数字输入通道&#xff0c;涵盖了干湿节点的识别功能&#xff0c;适用于多种开关量信号的读取&#xff1b;同时&a…

(八)springboot实战——springboot3下的webflux项目全局异常处理

前言 在webflux响应式编程中&#xff0c;如何处理系统运行时异常是本节的主要内容。在传统的Servlet阻塞式web项目中主要通过HandlerExceptionResolver处理器来处理&#xff0c;而在webflux响应式web项目中&#xff0c;则是通过DispatchExceptionHandler异常处理器来处理异常。…

[SWPUCTF 2018]SimplePHP1

打开环境 有查看文件跟上传文件&#xff0c;查看文件里面显示没有文件url貌似可以文件读取 上传文件里面可以上传文件。 先看一下可不可以文件读取 /etc/passwd不能读取&#xff0c;源码提示flag在f1ag.php 看看能不能读取当前的文件&#xff0c; 先把代码摘下来 file.php …

JavaScript 之 作用域变量提升闭包

一、JavaScript 代码的执行 浏览器内核是由两部分组成的&#xff0c;以 webkit 为例 WebCore&#xff1a;负责HTML解析、布局、渲染等等相关的工作JavaScriptCore&#xff1a;解析、执行 JavaScript 代码 另外一个强大的 JavaScript 引擎就是 V8 引擎 二、深入 V8 引擎原理 …

Java面向对象三大特征之多态

在之前的文章&#xff0c;我们分别介绍了类与对象、面向对象三大特征的封装、以及继承&#xff08;一&#xff09;、继承&#xff08;二&#xff09;。这一篇文章&#xff0c;我们介绍Java面向对象三大特征的最后一个——多态。 多态 多态的概述 概念&#xff1a;完成某个行为…

CVE-2024-23897 Jenkins 任意文件读取漏洞

项目介绍 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插…

Java集合相关面试题

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…

C# 设置一个定时器函数

C#中&#xff0c;创建设置一个定时器&#xff0c;能够定时中断执行特定操作&#xff0c;可以用于发送心跳、正计时和倒计时等。 本文对C#的定时器简单封装一下&#xff0c;哎&#xff0c;以方便定时器的创建。 定义 using Timer System.Timers.Timer;class SetTimer {Timer …

OSPF协议基础(OSPF工作过程)

目录 OSPF基本工作原理邻居建立过程Router ID发现并建立邻居 - Hello报文OSPF邻居建立过程 链路状态信息丰富的数据链路层支持能力网络类型 - P2P网络网络类型 - 广播型网络网络类型 - NBMA网络网络类型 - P2MP网络OSPF的度量方式 报文类型及作用OSPF协议报文头部OSPF报文类型O…