【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别

目录

  • 一、 动态SQL
      • 1.1 \<if>标签
      • 1.2 \<trim>标签
      • 1.3 \<where>标签
      • 1.4 \<set>标签
      • 1.5 \<foreach>标签
      • 1.6 \<include>标签
  • 二、 #{}与${}的区别
      • 2.1 #{}是预编译sql,${}是即时sql
      • 2.2 SQL注入
      • 2.3 #{}性能高于${}
      • 2.4 ${}用于排序功能

一、 动态SQL

什么是动态SQL,简单来说就是为了满足我们的条件可以将不同是SQL语句进行拼接,来使用.

1.1 <if>标签

在我们编程SQL语句中,时常有些参数不知道是否传参,在以往的编程中我们是使用if语句进行判读,在这里也同样如此,只是换成了<if>标签进行判断。
<if>标签的代码如下:

<if test="gender != null">
gender,
</if>

使用<if>标签将我们要判断的内容包裹起来即可。

1.2 <trim>标签

在我们判断的时候,有时会有多余的标点符号或是我们想要在sql语句前添加一下其它关键词,这时候就该<trim>标签派上用场了。
<trim>标签一共有四个属性,记住了属性是添加在<trim 属性>中的,记住添加的位置.
有以下四个属性:

  • prefix:表⽰整个语句块,以prefix的值作为前缀
  • suffix:表⽰整个语句块,以suffix的值作为后缀
  • prefixOverrides:表⽰整个语句块要去除掉的前缀
  • suffixOverrides:表⽰整个语句块要去除掉的后缀

举例代码如下:

<trim prefix="(" suffix=")" suffixOverrides=","><if test="username !=null">username,</if><if test="password !=null">`password`,</if><if test="age != null">age,</if><if test="gender != null">gender,</if><if test="phone != null">phone,</if></trim>

可以看到动态SQL是可以一起进行拼接使用的,在举例的该段代码中用到了,prefix用来在前缀添加、suffix用来后缀添加、suffixOverrides用来删除后缀标点,相信举了这个例子另外的的一个predixOverrides也会用了吧!

1.3 <where>标签

在SQL语句中,where关键字一般是用来进行条件判断的,在动态SQL中也是如此,只是我们给它换成<where>的标签形式会更加合理方便
代码如下:

<where><if test="age != null">and age = #{age}</if><if test="gender != null">and gender = #{gender}</if><if test="deleteFlag != null">and delete_flag = #{deleteFlag}</if></where>

在动态SQL中使用<where>标签能够在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或OR

1.4 <set>标签

<set>标签标签一般用在修改数据库的SQL语句中,可以使⽤标签来指定动态内容.
代码如下:

<set><if test="username != null">username = #{username},</if><if test="deleteFlag != null">delete_flag = #{deleteFlag},</if></set>

<set> :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

1.5 <foreach>标签

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:

• collection:绑定⽅法参数中的集合,如List,Set,Map或数组对象
• item:遍历时的每⼀个对象
•open:语句块开头的字符串
• close:语句块结束的字符串
• separator:每次遍历之间间隔的字符串

代码如下:

<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}
</foreach>

使用<foreach>标签就跟使用常见代码中的foreach用法一样,都是用来遍历数组等结构里的每一个元素.

1.6 <include>标签

在xml映射⽂件中配置的SQL,有时可能会存在很多重复的⽚段,此时就会存在很多冗余的代码,而<include>就是将重复的代码提取出来,在后面使用该重复代码中直接拿出来就行了,这里与resultMapper倒是有点相似.

我们可以对重复的代码⽚段进⾏抽取,将其通过 <sql> 标签封装到⼀个SQL⽚段,然后再通过

<include> 标签进⾏引⽤。

<sql> :定义可重⽤的SQL⽚段

<include>:通过属性refid,指定包含的SQL⽚段

展示定义重复的代码-<sql>标签如下:

<sql id="allColumn">id, username, age, gender, phone, delete_flag, create_time,update_time
</sql>

使用<include>标签调用已经定义好的代码块如下:

<include refid="allColumn"></include>

通过<sql>标签定义的属性名进行调用.

二、 #{}与${}的区别

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

#{}和${}都是在MyBatis操作数据库时进行取值的操作,且两者有以下三点区别,可能平时#{}是用的最多的,但既然${}存在便有其存在的价值和用处。
#{}和${}的区别:

  1. #{}是预编译sql,${}是即时sql

  2. #{}防止了sql注入,而${}可能被sql注入

  3. #{}的缓存性能比${}强大

  4. ${}特殊用处:数据库进行排序…等操作时

2.1 #{}是预编译sql,${}是即时sql

#{}是预编译sql,简单来说就是在程序编译时,用?来作占位符,然后根据传入的参数类型进行填充,如果传入的参数是String类型,则在填充时会自动给数据添加双引号"",来表示该字符串。
sql代码如下:

select username, `password`, age, gender, phone from userinfo where id= ?

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

然而${}是即时SQL简单来说就是没有占位符,不管你输入的数据是啥,它直接给你填充到参数的位置上去,即使是字符串类型也没有特殊处理,这时为了保证SQL正确,我们要自己手动添加""。
下面是使用${}时的SQL代码:

@Select("select username, `password`, age, gender, phone from userinfo where
id= ${id} ")
UserInfo queryById(Integer id);

代码运行的结果是:
在这里插入图片描述
可以看到,我们输入的参数直接添加到了SQL语句中了,这就是即时SQL-${}

小总结:

从上⾯例⼦可以看出:
#{} 使⽤的是预编译SQL,通过 ? 占位的⽅式,提前对SQL进⾏编译,然后把参数填充到SQL语句中.

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

2.2 SQL注入

首先来了解一下什么是SQL注入,SQL注入是由于前后端的漏洞而导致的Bug,黑客攻击人员可以通过前端的登录页面将数据输入到数据库,以达到修改甚至是删除数据库的目的。
通过上面学习我们可知,#{}是预编译SQL,而${}是即时SQL,当黑客在前端输入的数据是字符型sql“delete 数据库 ”,如果我们后端是用预编译SQL-#{}来取值的话,系统会看它是字符类型而添加"",进而导致SQL语句错误无法执行。

而使用即时SQL的话,是直接进行SQL拼接,会把delete database数据库直接拼接上去不带引号,这时数据库执行就会成功,把该公司的数据库删除掉。

小总结:

#{}会根据数据类型进行判断是否添加双引号""
KaTeX parse error: Expected 'EOF', got '#' at position 21: …拼接上去,使数据库被黑客攻击 #̲{}能够防止SQL注入,而{}会被SQL注入攻击

2.3 #{}性能高于${}

绝⼤多数情况下,某⼀条SQL语句可能会被反复调⽤执⾏,或者每次执⾏的时候只有个别的值不同(⽐如select的where⼦句值不同,update的set⼦句值不同,insert的values值不同).
如果每次都需要经过上⾯的语法解析,SQL优化、SQL编译等,则效率就明显不⾏了.
在这里插入图片描述
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译(只是输⼊的参数不同),省去了解析优化等过程,以此来提⾼效率

2.4 ${}用于排序功能

${}会有SQL注⼊的⻛险,所以我们尽量使⽤#{}完成查询,所谓它的存在就有一定的道理,如下在排序时就要用到即时SQL了。

@Select("select id, username, age, gender, phone, delete_flag, create_time,
update_time " +
"from userinfo order by id ${sort} ")
List<UserInfo> queryAllUserBySort(String sort);

使⽤${sort} 可以实现排序查询,⽽使⽤#{sort} 就不能实现排序查询了.
注意:此处sort参数为String类型,但是SQL语句中排序规则是不需要加引号 ‘’ 的,所以此时的${sort} 也不加引号,而使用#{}则会自动添加双引号"",就无法实现排序的功能了。

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

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

相关文章

洛谷 P10566 「Daily OI Round 4」Analysis 题解

先弄个 ASCII 码表&#xff1a; 分析 很明显&#xff0c;想要节省时间&#xff0c;就要把这些字符转换成和它们的 ASCII 值最接近的大写字母。 通过 ASCII 码表&#xff0c;很容易就可以发现&#xff1a; ASCII 值与数字最接近的大写字母是 A \texttt A A。ASCII 值与小写…

JVM学习-监控工具(二)

jmap&#xff1a;导出内存映像文件&内存使用情况 基本情况 jmap(JVM Memory Map)&#xff1a;一方法获取dump文件(堆转储快照文件&#xff0c;二进制文件)&#xff0c;还可以获取目标Java进程的内存相关信息&#xff0c;包括Java堆各区域的使用情况、堆中对象的统计信息、…

多线程新手村5--线程池

1.1 线程池是什么 线程诞生的意义是因为进程的创建/销毁开销太大&#xff0c;所以使用线程提高代码的执行效率&#xff1b;那如果想要进一步提升执行效率&#xff0c;该怎么办呢&#xff1f;有一个方法是使用线程池。 首先&#xff0c;什么是线程池&#xff1a;池就是池子&am…

奶茶店、女装店、餐饮店是高危创业方向,原因如下:

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 现在的俊男靓女们&#xff0c;心中都有一个执念&#xff1a; (1)想证明自己了&#xff0c;开个奶茶去…… (2)想多赚点钱了&#xff0c;加盟餐饮店去…… (3)工作不顺心了&#xff0c;搞个女装店去…… 但凡抱着…

102.网络游戏逆向分析与漏洞攻防-ui界面的设计-反隐身功能的界面设计与实现(有不使用MFC生成,自己手写代码创建复选框与事件的例子)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

独立游戏开发的 6 个步骤

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

discuz论坛怎么修改备案信息

大家好&#xff0c;今天给大家分享下discuz如何填写备案信息并且展示在网站首页。大家都知道国内网站都需要备案&#xff0c;不通过备案的网站上是没办法通过域名打开的。大家也可以通过搜索网创有方&#xff0c;或者直接点击网创有方 查看悬挂备案号后的效果。 首先大家可以看…

MySQL表的增删改查初阶(上篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

成人本科毕业论文怎么写?分享自己的经验

撰写成人本科毕业论文是一个系统而深入的过程&#xff0c;以下是我个人的经验分享&#xff0c;希望能帮助你更好地完成这一任务&#xff1a; 1. 明确论文选题 兴趣与专长&#xff1a;选择自己感兴趣且有一定专长的领域&#xff0c;这样更容易深入研究。可行性&#xff1a;确保…

【全开源】种草分享|动态朋友圈|瀑布流|uniapp

一款基于FastadminThinkPHP和Uniapp开发的种草分享评论点赞消息提醒系统&#xff0c;发布动态&#xff0c;分享种草生活&#xff0c;可以收藏关注点赞&#xff0c;消息提醒&#xff0c;同时支持H5/小程序/app多端。 ​让每一次互动都不再错过&#x1f514; &#x1f331; 种草…

spring boot 中的异步@Async

spring boot 开启异步调用 1、启动类上添加EnableAsync注解&#xff0c;表示启动异步 2、在具体实现异步的方法上添加Async注解 package com.example.demo;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootAppli…

HTML5的标签(文本链接、图片路径详解)

目录 前言 一、文本链接 超链接表述 二、图片路径详解 绝对路径 相对路径 网络路径 前言 一、文本链接 超链接表述 HTML 使用标签<a>来设置超文本链接 超链接可以是一个字&#xff0c;一个词&#xff0c;或者一组词&#xff0c;也可以是一幅图像&#xff0c;…

[FreeRTOS 基础知识] 堆

文章目录 堆的概念使用C语言实现 堆堆空间解析 堆的概念 所谓的堆就是一块空间的内存&#xff0c;可以来管理这块内存。从这块内存中取出一部分然后再释放回去。 使用C语言实现 堆 char heap_buf[1024]; // 定义一个堆空间 int pos0; // 当前…

文件上传题目练习

[HNCTF 2022 Week1]easy_upload 先尝试上传一个php文件&#xff0c;发现直接就成功了 用蚁剑测试连接成功 找到flag [NISACTF 2022]bingdundun~ 白名单上传 这里因为尝试了很多绕过方式都不成功&#xff0c;去搜索了一下wp&#xff0c;发现要用到Phar://伪协议 补充&#xff…

恒创科技:无法与服务器建立安全连接怎么解决?

在使用互联网服务时&#xff0c;有时会出现无法与服务器建立安全连接的问题&#xff0c;此错误消息通常出现在尝试访问需要安全连接的网站(例如使用 HTTPS 的网站)时&#xff0c;这可能是由于多种原因造成的&#xff0c;以下是一些常见的解决方法&#xff0c;帮助你解决问题。 …

VR导航的实现原理、技术优势和应用场景

VR导航通过虚拟现实技术提供沉浸式环境&#xff0c;结合室内定位技术实现精准导航。目前&#xff0c;VR导航已在多个领域展现出其独特的价值和潜力&#xff0c;预示着智能导航系统的未来发展。 一、实现原理 VR导航技术依托于虚拟现实(VR)和室内定位系统。VR技术利用计算机模…

先进的无人机GPS/GNSS模块解决方案

由于多星座支持和增强的信号接收能力&#xff0c;先进的GNSS模块提供了更高的精度和可靠性。集成传感器融合补偿信号中断&#xff0c;实现无缝导航。内置实时运动学(RTK)支持提供厘米级的定位精度。这些模块还优先考虑低功耗和紧凑的尺寸&#xff0c;确保更长的飞行时间和对无人…

2024.6.2练习情况—整数二分

2024.6.2练习情况—整数二分 一、例题Acwing789.数的范围 题目 代码 #include<iostream> #include<cstring> using namespace std; const int N 100100; int n,q,k;//题中变量 int arr[N]; //找左端点 void querryleft(int arr[],int k){ int l0,rn-1; …

list~模拟实现

目录 list的介绍及使用 list的底层结构 节点类的实现 list的实现 构造函数 拷贝构造 方法一&#xff1a;方法二&#xff1a; 析构函数 赋值重载 insert / erase push_/pop_(尾插/尾删/头插/头删) begin和end&#xff08;在已建立迭代器的基础上&#xff09; 迭代…

React@16.x(17)Portals

目录 1&#xff0c;使用2&#xff0c;事件冒泡 一句话总结&#xff1a;和 Vue3 的 Teleport 一个效果。 1&#xff0c;使用 import React, { PureComponent } from "react"; import ReactDOM from "react-dom";// 返回一个 React 元素&#xff08;ReactNo…