#{}和${}的区别是什么

news/2024/5/17 20:09:20/文章来源:https://www.cnblogs.com/javaxubo/p/16608519.html

#{}和${}的区别是什么

动态 sql 是 MyBatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 MyBatis 会对其进行动态解析。MyBatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}。

区别

1)#{}是预编译处理,$ {}是字符串替换。

2)MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值;MyBatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。

3)使用 #{} 可以有效的防止SQL注入,提高系统安全性。

项目实战中使用,请阅读我博客中Java项目实战分类中的--MySQL中in('5,6,7')只取第一个id为5对应的数据的思考一文,谢谢。

要理解记忆这个题目,我觉得要抓住两点:

(1)$ 符号一般用来当作占位符,常使用Linux脚本的同学应该对此有更深的体会吧。既然是占位符,当然就是被用来替换的。知道了这点就能很容易区分$和#,从而不容易记错了。

(2)预编译的机制。预编译是提前对SQL语句进行预编译,而其后注入的参数将不会再进行SQL编译。我们知道,SQL注入是发生在编译的过程中,因为恶意注入了某些特殊字符,最后被编译成了恶意的执行操作。而预编译机制则可以很好的防止SQL注入。在某些特殊场合下只能用${},不能用#{}。例如:在使用排序时ORDER BY ${id},如果使用#{id},则会被解析成ORDER BY “id”,这显然是一种错误的写法。

示例讲解

<select id="selectPerson" parameterType="int" resultType="hashmap">SELECT * FROM PERSON WHERE ID = #{id}
</select>

这个语句名为 selectPerson,接受一个 int(或 Integer)类型的参数,并返回一个 HashMap 类型的对象,其中的键是列名,值便是结果行中的对应值。

注意参数符号:#{id}

这就告诉 MyBatis 创建一个预处理语句(PreparedStatement)参数,在 JDBC 中,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:

// 近似的 JDBC 代码,非 MyBatis 代码...
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

真实项目中防止SQL注入:

Mabatis中模糊查询防止sql注入

Mysql:

select * from user where name like concat('%', #{name}, '%')

image-20220820200930746

Oracle:

select * from user where name like '%' || #{name} || '%'

SQLServer:

select * from user where name like '%' + #{name} + '%'

以下内容是对上述知识的扩展和理解

1.防止恶义SQL语法注入实例

实例一

String sql = "select * from tb_name where name = '" + varname + "' and passwd = '" + varpasswd + "' ";

如果我们把['or'1'='1]作为varpasswd传入进来.用户名随意,看看会成为什么?

select * from tb_name = 随意' and passwd = ' ' or '1'='1';

因为'1'='1'肯定成立,所以可以任何通过验证

实例二

select * from ${tableName} where name = #{name}

在这个例子中,如果表名为

user; delete user; --

则动态解析之后 sql 如下:

select * from user; delete user; -- where name = ?;

--之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。

2.预编译

定义:指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。

为什么需要预编译?

JDBC 中使用对象 PreparedStatement 来抽象预编译语句,使用预编译

1)预编译阶段可以优化 sql 的执行

预编译之后的 sql 多数情况下可以直接执行,DBMS 不需要再次编译,越复杂的sql,编译的复杂度将越大,预编译阶段可以合并多次操作为一个操作。

2)****预编译语句对象可以重复利用

把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。

MyBatis 默认情况下,将对所有的 sql 进行预编译。

3.MyBatis sql 动态解析

MyBatis 在调用 connection 进行 sql 预编译之前,会对sql语句进行动态解析,动态解析主要包含如下的功能:

占位符的处理

动态sql的处理

参数类型校验

4.DBMS和DB的关系

DBMS数据库管理系统(databasemanagementsystem)是一种操纵和管理数据库的大型软件,是用于建立、使用和维护数据库(DB)。它对数据库进行统一的管理和控制,以保证数据库的安全性和完整性。用户通过DBMS访问数据库(DB)中的数据。

MySQL是一个关系型数据库管理系统。

数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。

参考

https://www.cnblogs.com/liaowenhui/p/12217959.html

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

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

相关文章

Mybatis组件介绍

核心组件 SqlSessionFactoryBuilder SqlSessionFactoryBuilder的作用就是通过XML或者Java代码来建造一个工厂(SqlSessionFactory),并且可以通过它建造多个这样的工厂。一旦完成建造工厂的任务,我们就应该废弃它,回收空间。所以它的生命周期只存在方法局部,完成工厂的建造即…

JAVA入门2022年8月19日

第一节 1.注释是什么写在程序中对程序进行解释说明的文字。 2.java中书写注释的方法有几种,各自有什么不同// 单行注释/* */ 多行注释/** */ 文档注释 3.注释有什么特点不进行编译,不影响程序的执行 4.注释的快捷键是怎么样的 第二节1.字面…

vue的生命周期

一、Vue 的生命周期 一、Vue 的生命周期流程图二、Vue 生命周期的具体    生命周期 描述beforeCreate 组件实例被创建之初created 组件实例已经完成创建beforeMount 组件挂载之前mounted 组件挂载到实例上去之后beforeUpdate 组件数据发生变化,更新之前updated 组件数据更新…

spring源码学习笔记1——解析xml生成BeanDefinition的过程解析

spring源码学习笔记1——解析xml生成BeanDefinition的过程解析 一丶Spring解析Xml生成BeanDefinition的流程 1.指定xml路径 解析xml首先需要知道xml的位置,如下我们构造了ApplicationContext ApplicationContext context =new ClassPathXmlApplicationContext("bean.xml&…

IOC

介绍 什么是SpringIOC,就是把每一个bean(实体类)与bean(实体类)之间的关系交给第三方容器进行管理。关键类BeanFactory IOC的顶层容器,描述了IOC的规范。 BeanFactory是一个接口,是Spring中工厂的顶层规范,IOC的核心接口。 定义了getBean()、containsBean()等管理Bean的通用…

JUC进阶

JUC进阶 wait和sleep的区别sleep是Thread的静态方法,wait是Object方法sleep不会释放锁,它也不需要占用锁,wait会释放锁但调用它的前提是当前线程占有锁wait必须在同步代码块中Lock锁public class LockTest { public static void main(String[] args) { Ticket t…

Spring 03: 基于xml的构造方法注入

构造方法注入具体有3种注入方式:通过构造方法的 a.参数名称注入 b.参数下标注入 c.默认参数顺序注入参数名称注入School实体类package com.example.pojo03;public class School {private String name;private String address;@Overridepublic String toString() {return &…

Vmware 安装CentOS 7

Vmware 安装CentOS 7 创建虚拟机 1、新建虚拟机,选择自定义(高级),下一步。其他默认下一步。选择操作系统Linux,CentOS 7 64位,下一步。输入主机名称,虚拟机存储位置。 2、输入内核数量3、输入内存大小,下一步,其他默认下一步。4、指定磁盘大小,下一步5、自定义硬件,…

深度学习基础课:课程介绍

大家好~我开设了“深度学习基础班”的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序 本文为第一节课:课程介绍的复盘文章深度学习基础课:课程介绍 大家好~我开设了“深度学习基础班”的线上课程,带领同学从0开始学习全连接…

一台服务器​最大并发 TCP 连接数多少

一台服务器​最大并发 TCP 连接数多少 入门小站 入门小站 2022-07-06 22:10 发表于湖北收录于合集#Linux485个 #tcp4个首先,问题中描述的65535个连接指的是客户端连接数的限制。在tcp应用中,server事先在某个固定端口监听,client主动发起连接,经过三路握手后建立tcp连接。那…

js的原型

prototype 概述:所有的函数都拥有一个属性 这个属性称为prototype 他是一个对象空间(里面就可以存放对应的数据)他被称为显式原型从上述代码 大家可以看到对应的构造函数的prototype和对应的实例对象的 __proto__ 是相等,那么也就证明了对应俩个内容其实是一个对象。那么我…

Condition介绍

Condition Condition是一种多线程通信工具,表示多线程下参与数据竞争的线程的一种状态,主要负责多线程环境下对线程的挂起和唤醒工作。 方法 // ========== 阻塞 ========== // 造成当前线程在接到信号或被中断之前一直处于等待状态。 void await() throws InterruptedExcept…

解决goland在mac m1下无法调试问题

背景 新电脑mac m1 goland调试抛出异常 异常信息 第一次异常信息 could not launch process: can not run under Rosetta, check that the installed build of Go is right for your CPU architecture 原因是goland版本安装错了. 下载地址:https://www.jetbrains.com/zh-cn/go…

排序(上)

目录冒泡排序(Bubble Sort)插入排序(Insertion Sort)选择排序(Selection Sort)冒泡排序和插入排序的比较 最经典的、最常用的有:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序 冒泡排序(Bubble Sort) 冒泡排序只会操作相邻的两个数据…

Codeforces Round #815 (Div. 2) 题解

Codeforces Round #815 (Div. 2) 全场题解CF1720A. Burenka Plays with Fractions给出两个分数 $ \dfrac{a}{b}$ 和 \(\dfrac{c}{d}\) ,你每次操作能够选择其中一个分数的分子或分母,将其乘上任意一个整数(当然不能对分母乘 \(0\))。要求求出能够使两个分数相等的最小操作次…

2022 牛客多校 Extra 第九场部分题解

2022 牛客多校第九场 & Extra 部分题解 前段时间沉迷生活大爆炸 & 原神 & vtb & galgame & 番无法自拔,因此咕到现在。。。 Cmostp 挺妙的题。本以为有一只 log 的做法。 覆盖后的颜色变换不多,可以用 set+树剖或者阉割版的lct+树状数组,我写了后者,把…

【小迪安全】04:基础入门-web源码扩展

(XYCMS搬家公司建站系统) 查找数据库文件路径: 发现后缀名为mdb文件——为asp网站特有的 打开mdb文件找到 admin_user数据库可以找到用户名和密码

解决无法访问GitHub

一、获取IP地址可以直接通过网站 查询域名 github.com 的IP地址,无论哪种方法一定得是通过自己本机查到的IP,网上别人查到的IP你不一定有用。https://www.ipaddress.com/二、修改hosts文件 Windows hosts文件路径: C:\Windows\System32\drivers\etc 在对应目录找到hosts文件,…

Intellij IDEA 快速生成注释模板教程

生成类注释 File–>settings–>Editor–>File and Code Templates–>Class (1)@BelongsProject:当前项目的名称 (2)@BelongsPackage:当前包的名称 (3)@Author:作者姓名(可以写死,写成你的名字) (4)@CreateTime:该类创建的时间 (5)@Description:对…

第一章 计算机硬件基础

1、数据的表示R进制的表示(R可为二、八、十、十六) 原则:逢R进一 Decimail 十进制;Binary 二进制; Octal 八进制;Hex 十六进制R进制转十进制(按权展开) 以二进制1101为例:十进制转二进制(短除法)二进制与八、十六进制之间的转换问题:为啥八进制数对应三位二进制数,…