【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.hqwc.cn/news/434006.html

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

相关文章

数据库之 基础概念、安装mysql、sql语句基础

数据库之 基础概念、安装mysql、sql语句基础 【一】存储数据的演变过程&#xff1a; 文件存储&#xff1a; 初始阶段随意存放数据到文件&#xff0c;格式任意。目录规范引入&#xff1a; 软件开发使用目录规范&#xff0c;限制数据位置&#xff0c;建立专门文件夹。本地数据存…

java版代码生成器

之前实现的JRT代码生成器是M版的&#xff0c;那么用户必须用M库才能有代码生成器的功能。为了提供给就是不用M库的用户使用&#xff0c;JRT再提供脚本版的java代码生成器&#xff0c;方便直接连关系库生成JRT的代码。 实现&#xff1a; import JRT.Core.MultiPlatform.JRTCon…

接口测试怎么测?接口测试的流程和步骤(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 一、什么是接口测试 我们要想知道接口测试怎么做&#xff0c;首先要明白接口测试是什么?一般…

<蓝桥杯软件赛>零基础备赛20周--第18周--动态规划初步

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上交流答疑&am…

HCS-华为云Stack-FusionSphere

HCS-华为云Stack-FusionSphere FusionSphere是华为面向多行业客户推出的云操作系统解决方案。 FusionSphere基于开放的OpenStack架构&#xff0c;并针对企业云计算数据中心场景进行设计和优化&#xff0c;提供了强大的虚拟化功能和资源池管理能力、丰富的云基础服务组件和工具…

栈和队列的动态实现(C语言实现)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

【LeetCode】112. 路径总和(简单)——代码随想录算法训练营Day18

题目链接&#xff1a;112. 路径总和 题目描述 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&…

ENVI下基于知识决策树提取地表覆盖信息

基于知识的决策树分类是基于遥感影像数据及其他空间数据,通过专家经验总结、简单的数学统计和归纳方法等,获得分类规则并进行遥感分类。分类规则易于理解,分类过程也符合人的认知过程,最大的特点是利用的多源数据。 决策树分类主要的工作是获取规则,本文介绍使用CART算法…

第17章_反射机制(理解Class类并获取Class实例,类的加载与ClassLoader的理解,反射的基本应用,读取注解信息,体会反射的动态性)

文章目录 第17章_反射机制本章专题与脉络1. 反射(Reflection)的概念1.1 反射的出现背景1.2 反射概述1.3 Java反射机制研究及应用1.4 反射相关的主要API1.5 反射的优缺点 2. 理解Class类并获取Class实例2.1 理解Class2.1.1 理论上2.1.2 内存结构上 2.2 获取Class类的实例(四种方…

每日一题——LeetCode1346.检查整数及其两倍数是否存在

方法一 循环查找 用indexOf查找每个元素的两倍是否存在在数组中&#xff0c;找到了就直接return true&#xff0c;循环结束还没找到就return false var checkIfExist function(arr) {for(let i0;i<arr.length;i){let index arr.indexOf(arr[i]*2)if(index>0 &&…

小土堆pytorch学习笔记003 | 下载数据集dataset 及报错处理

目录 1、下载数据集 2、展示数据集里面的内容 3、DataLoader 的使用 例子&#xff1a; 结果展示&#xff1a; 1、下载数据集 # 数据集import torchvisiontrain_set torchvision.datasets.CIFAR10(root"./test10_dataset", trainTrue, downloadTrue) test_set …

CAD-autolisp(二)——选择集、命令行设置对话框、符号表

目录 一、选择集1.1 选择集的创建1.2 选择集的编辑1.3 操作选择集 二、命令行设置对话框2.1 设置图层2.2 加载线型2.3 设置字体样式2.4 设置标注样式&#xff08;了解即可&#xff09; 三、符号表3.1 简介3.2 符号表查找3.2 符号表删改增 一、选择集 定义&#xff1a;批量选择…