JavaEE进阶----18.<Mybatis补充($和#的区别+数据库连接池)>

详解了

1.$和#的区别

2.数据库连接池。

3.简单了解MySQL企业开发规范

一、Mybatis面试题:$和#的区别是什么?

MyBatis 参数赋值有两种方式,咱们前面使用了 #{} 进行赋值,接下来我们看下二者的区别。

1.1 #是预编译SQL,$是即时SQL

SQL执行流程

1.语法解析,校验SQL有没有问题。

2.SQL优化,编译,制定执行计划。

3.执行SQL

因此

①#是预编译SQL,不是一个完整的SQL。可以进行缓存,参数是不固定的,性能更高。

   $时即时SQL,可以直接编译。但不能进行缓存,参数是固定的。性能更低。

②$存在SQL注入的风险

我们分别使用Integer与String类型参数举例

#是预编译SQL,预编译处理。

$是即时SQL,字符直接替换。

预编译SQL的性能更高一点。可以进行缓存

我们编写如下代码。用#和$分别去取值Integer类型参数和String类型参数。

参数为Integer类型时

使用#符号:预编译SQL。(select * from userinfo where id = ?)

@Select("select * from userinfo where id = #{userId}")
UserInfo queryUserInfo(Integer userId);


 使用$符号:即时SQL。(select * from userinfo where id = 1)

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

2.参数为String类型时

使用 # 符号:预编译SQL。(select * from userinfo where username = ?)

# 会拼接引号。

因此 # 适用于需要拼接引号的情况。

而不用拼接引号的情况就是 $ 符号发挥作用的时候了。

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

 使用$符号:即时SQL。(select * from userinfo where username = admin)(报错)

$不会拼接引号,而是直接拼接上。 

    @Select("select * from userinfo where username = ${name}")
    List<UserInfo> queryUserByName2(@Param("name") String name);
    @Test
    void queryUserByName2() {
        log.info(userInfoMapper.queryUserByName2("admin").toString());
    }

 使用$符号:即时SQL。(select * from userinfo where username = 'admin')

$不会拼接引号,而是直接拼接上。 因此注意加单引号。或者双引号。

这样就不会报错了

select * from userinfo where username = '${name}'

    @Select("select * from userinfo where username = '${name}'")
    List<UserInfo> queryUserByName2(@Param("name") String name);
    @Test
    void queryUserByName2() {
        log.info(userInfoMapper.queryUserByName2("admin").toString());
    }

注:

如果只有一条结果,那么使用对象接收也可以,使用List<UserInfo>接收也可以。

如果有多条结果,那么只能使用 List 来接收


1.2最主要区别($存在SQL注入的问题。

1.1.1$存在SQL注入的问题

最主要的区别是:$存在SQL注入的问题。

SQL注入:

是通过操作输入的数据(参数),来修改事先定义好的SQL语句(不完整SQL),以达到执行的代码对服务器进行攻击的方法。 

也就是把参数作为SQL的一部分,以达到对服务器进行攻击的目的。

示例:

这个就相当于

select * from userinfo where username = ture 

  • 空字符串 ' ' 的含义

    • 在 SQL 中,空字符串 ' ' 是一个非空的字符串,因此在布尔上下文中,它会被视为真值(TRUE)。
    • 因为空字符串不是NULL,所以在逻辑表达式中,它被认为是“有值”的。
  • 1 = '1' 的逻辑

    • SQL 中,字符串 '1' 和整数 1 在比较时通常会隐式转换为相同的数据类型。1 = '1' 会被解释为 1 = 1,结果为 TRUE

执行SQL语句后,我们得到的结果是将表内所有内容都打印出来了。相当于没有where

由于存在SQL注入的问题因此$符号不被广泛使用了。

早期SQL注入的问题:

可以将表删掉,

也可以更新表的数据,因此SQL注入是一个非常严重的问题。

delete的问题不存在了,是因为Mybatis帮我们拦截了,例如我们@select注解中有delete操作,那么就会将之拦截。

通过SQL注入完成无密码就可以登录

也不是说使用$就一定会存在SQL注入问题。而是看你的代码如何去实现的

模拟SQL注入 完成用户登录 代码演示:

1.在Controller包控制器层中(也算是三层架构中的视图层)
​​​​​​​​​    @RequestMapping("/login")
    public UserInfo login(String userName,String password){
        return userService.queryUserByNameAndPassword(userName,password);
    }
2.在Service服务层包中
    public UserInfo queryUserByNameAndPassword(String name,String password) {
        List<UserInfo> userInfos = userInfoMapper.queryUserByNameAndPassword(name,password);
        if(!userInfos.isEmpty()){
            //如果查出来
            return userInfos.get(0);
        }
        //如果没查出来
        return null;
    }
3.在Mapper数据访问层中:

​​​​​​​

4. 访问的数据库表如下

5.最终访问的结果如下:

我们发现:

当我们的密码输入为'or 1='1时数据也可以被访问到,这就是很严重的SQL注入问题。  

这就是一个漏洞。

这并不是说如果你使用$符号就一定有问题。如果Mapper层代码我们使用

对象UserInfo来接收的话,那么我们使用' or 1='1也登录不进去,因为这样会报错。是因为UserInfo默认返回一个对象的数据。而如果存在SQL注入,就会返回多个对象的数据。

如果只有一条结果,那么使用对象接收也可以,使用List<UserInfo>接收也可以。

如果有多条结果,那么只能使用 List 来接收。如果使用UserInfo对象来接收就会报错。

还有一些其他地方

如果我们根据userName去查再去通过password校验,这种情况使用' or 1='1也登录不进去

1.3在使用上的其他区别

表名,字段名作为参数时。这些情况需要使用${ }。

1.3.1使用淘宝进行排序问题(不能使用#):

此时需要使用$符号,

注:

此时也存在SQL注入的风险

解决办法:如果不让用户传参的话,那么就不存在SQL注入风险了

也就是不给用户在用$取值的输入框。

如何来去做呢?请往下看

SQL语句七 由Id进行倒序排序。

select * from userinfo order by id desc

假如我们这样在Mapper包中写数据。那么就会报错。

SQL语句出错,是因为#若参数是字符串会默认加上' '此时

SQL语句变成了

select * from userinfo order by id 'desc'

因此会报错,如果我们改成用$来取值,那么此时就可以编译通过了

注:

此时也存在SQL注入的风险,解决办法:如果不让用户传参的话,那么就不存在SQL注入风险了

也就是不给用户在用$取值的输入框。

如何来去做呢?请往下看

$存在SQL注入风险,如何处理?

实现方式非常多,简单列举以下方式

例如1:不接收用户输入的参数,参数由后台来处理。

代码要写的很严谨,就不存在SQL注入问题了。

升序:url1

降序:url2

不接收用户输入的参数,参数由后台来处理。

对参数进行校验,只接受desc(降序)      /      asc(升序) 这两个参数

在后端进行校验。如果不是这两个参数则立马报错进行处理。

order参数是Controller包中被用户传进来的

还有哪些情况#不能使用

不需要加引号的时候,比如表名,字段名。

表名,字段名作为变量的时候,

表明作为变量:

在分库分表的情况下,若将userinfo这张表分成userinfo1,userinfo2,...userinfo10这十张表,我们查询的时候,根据一定的规则,看哪张表里有我们想要的userId,此时表名就是变量了。

字段名作为变量:

1.一些大公司不让直接连数据库(不然账号密码直接登录数据库),连了就会有风险,如何规避风险,而是开发一个MySQL客户端,申请权限就可以直接连数据库不需要账号密码。需要解析SQL。字段都是生成的,

2.数据的导出,若只想导出某一些列,此时列名就会被作为变量。#不能使用。

1.3.2模糊查询问题(不能直接使用#,需要通过CONCAT(str1,str2,..)方式再用#实现):

SQL语句八:模糊查询

select * from userinfo where username like "%需要查询的名字%"

例:select * from userinfo where username like "%admin%"

数据库表

我们在Mapper中写出如下代码进行迷糊查询并进行测试:

只查询出来了一条,因为输入结果为admin,我们虽然加了%%但是被弄丢了。因此相当于我们只查了admin没有进行模糊查询。相当于等号。

也就是拼接成了

select * from userinfo where username like admin 

相当于

select * from userinfo where username = admin

换一种写法,我们将百分号写在外面

又报错了,SQL语句出错。 拼接成了

select * from userinfo where username like %'admin'%

在里面又加上了引号。

因此模糊查询通过#无法实现。

通过$实现模糊查询

我们发现,成功得到了我们想要的结果。

模糊查询$存在SQL注入风险,如何处理?

使用MySQL的CONCAT(str1,str2,....)

CONCAT()是mysql内置函数

使用示例如下

select * from userinfo where username like CONCAT('%',admin,'%')

改成这种形式 就可以使用#来实现模糊查询

总结

#和$的区别

1.#是预编译SQL,预编译处理。$是即时SQL,字符直接替换。预编译SQL的性能更高一点。可以进行缓存

2.$存在SQL注入的风险。#{ }可以防止SQL注入。

3.查询语句中,可以使用#{ }推荐使用#{ }。#{ }不能完成如排序功能表名字段名作为参数时。这些情况需要使用${ }。

4.排序,模糊查询等方式不能直接用#来取值。排序可以进行校验,模糊查询可以通过使用MySQL内置函数进行转化再用#进行查询。

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

相同点:

#是取值用的

$也是取值用的

二、数据库连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接, 而不是再重新建立一个。

没有使用数据库连接池的情况:每次执行SQL语句,要先创建一个新的连接对象,然后执行SQL语句,SQL 语句执行完,再关闭连接对象释放资源。这种重复的创建连接,销毁连接比较消耗资源

使用数据库连接池的情况:程序启动时,会在数据库连接池中创建一定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执行SQL,SQL语句执行完,再把 Connection归还给连接池。 

使用数据库连接池的好处:

优点:

1. 减少了网络开销

2. 资源重用

3. 提升了系统的性能

常见数据库连接池:C3P0、DBCP、Druid、HiKari。

目前比较流行的数据库连接池是Hikari,Druid

2.1Hikari :

Hikari 是日语"光"的意思(ひかり),Hikari也是以追求性能极致为目标

是SpringBoot默认使用的数据库连接池

Hikaricp和Druid对比_数据库_晚风暖-华为云开发者联盟 (csdn.net)

2.2Druid

如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要引入相关依赖即可 

<dependency>

        <groupId>com.alibaba</groupId>

        <artifactId>druid-spring-boot-starter</artifactId>

        <version>1.1.17</version>

</dependency>

官方参考地址

Druid连接池是阿里巴巴开源的数据库连接池项目 功能强大,性能优秀是Java语言最好的数据库连接池之⼀。

学习文档:https://github.com/alibaba/druid/wiki/%E9%A6%96%E9%A1%B5

大总结

1.MySQL企业开发规范

重点:

1.表名,字段名用小写字母或数字,单词间用_分割。尽量避免出现数字开头或者两个下划线中间只出现数字。数据库字段名的修改代价很大,所以字段名称需要慎重考虑。

2.表必备三字段:id,create_time,update_time

3.在表查询中, 避免使用*作为查询的字段列表,标明需要哪些字段

2.#{} 和${} 区别

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

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

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

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

3.数据库连接池

目前比较流行的数据库连接池是

Hikari:是SpringBoot默认使用的数据库连接池

Druid:是阿里巴巴开源的数据库连接池项目。功能强大,性能优秀是Java语言最好的数据库连接池之⼀。

优点:

1. 减少了网络开销

2. 资源重用

3. 提升了系统的性能

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

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

相关文章

瑞格智慧心理服务平台 NPreenSMSList.asmx sql注入漏洞复现

0x01 产品描述&#xff1a; ‌ 瑞格智慧心理服务平台‌是一个集心理测评、心理咨询、心理危机干预、心理放松训练等功能于一体的综合性心理健康服务平台。该平台由北京瑞格心灵科技有限公司开发&#xff0c;旨在为用户提供全方位的心理健康服务。0x02 漏洞描述&#xff1a;…

Webserver(1.8)操作函数

目录 文件属性操作函数access函数chmod函数chown函数truncate函数 目录操作函数mkdir函数rmdir函数rename函数chdir函数*getcwd函数 目录遍历函数*opendir函数*readdir函数closedir函数 dup、dup2函数dupdup2 fcntl函数 文件属性操作函数 access函数 判断某个文件是否有某个权…

(49)MATLAB实现迫零均衡器原理与代码

文章目录 前言一、迫零均衡器设计说明二、迫零均衡器MATLAB源代码1.函数说明2.代码实现3.辅助函数 前言 使用MATLAB实现迫零均衡器。给出完整的MATLAB设计源代码。 一、迫零均衡器设计说明 理想的迫零均衡器有无限多个抽头权系数&#xff0c;是不能实现的&#xff0c;本文考虑…

springboot揭秘00-基于java配置的spring容器

文章目录 【README】【1】基本概念&#xff1a;Configuration与Bean【2】使用AnnotationConfigApplicationContext实例化spring容器【2.1】使用java配置简单构建spring容器【2.1.1】AnnotationConfigApplicationContext与Component及JSR-330注解类一起使用 【2.2】使用register…

线程和进程延续

1.线程和进程启动终止方式 1.创建子进程&#xff0c;子线程 2.退出进程/线程 3.回收僵尸进程资源 / 回收线程资源 4.进程终止函数 / 线程清理函数 2.线程状态切换 pthread_create()变为就绪态&#xff0c;调度后成为运行态&#xff0c;pthread_join()成为阻塞态…

为微信小程序换皮肤之配置vant

微信小程序自带的控件虽然具有很好的通用性和简洁性&#xff0c;但在面对一些复杂的交互场景和个性化的设计需求时&#xff0c;可能会显得力不从心。其功能的相对基础使得开发者在实现诸如多步骤复杂表单提交、实时数据交互与可视化展示、高度定制化的界面布局等方面&#xff0…

K8S配置storage-class

简介 Kubernetes支持NFS存储&#xff0c;需要安装nfs-subdir-external-provisioner&#xff0c;它是一个存储资源自动调配器&#xff0c;它可将现有的NFS服务器通过持久卷声明来支持Kubernetes持久卷的动态分配。该组件是对Kubernetes NFS-Client Provisioner的扩展&#xff0…

html生成图片方案总结

动态图片生成是我们日常开发中经常遇到的需求&#xff0c;比如宣传海报生成&#xff0c;电商商品图动态生成等&#xff0c;本文总结出三种常见的 HTML 生成图片的方案。 一、html2canvas html2canvas库能够将 HTML 元素渲染为 Canvas&#xff0c;然后将其转换为图片。它的优点…

【力扣刷题实战】相同的树

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 力扣题目&#xff1a; 相同的树 题目描述 示例 1&#xff1a; 示例 2&#xff1a; 示例 3&#xff1a; 解题思路 题目理解 算法选择 具体思路 解题要点 完整代码&#xff08;C语言&#xff09; 兄弟们共勉 &#…

如何使用AdsPower指纹浏览器克服爬虫技术限制,安全高效进行爬虫!

随着中国开发者日益成熟&#xff0c;应用质量明显提升&#xff0c;越来越多的开发者选择出海寻找机会扩大市场。但“应用出海”说起来容易&#xff0c;做起来难。其中&#xff0c;最大的困恼就是对海外市场缺乏了解。 很多开发者会选择使用网络爬虫&#xff08;Web Crawling&a…

Python小游戏18——中国象棋

首先&#xff0c;你需要安装Pygame库。如果你还没有安装它&#xff0c;可以使用以下命令进行安装&#xff1a; bash pip install pygame 运行结果 代码如下&#xff1a; python import pygame import sys # 初始化Pygame pygame.init() # 屏幕尺寸 SCREEN_WIDTH 800 SCREEN_HE…

轴承寿命预测 (Python 预测模型全家桶)

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客 Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客 Pytorch-Transformer轴承故障一维信号分类(三)-CSDN博客 三十多个开源…

【IC验证_systemverilog】信号类型

IC验证_systemverilog 1.信号声明2.变量类型3.数据类型4.符号 1.信号声明 语法&#xff1a; 变量类型 信号类型 符号转换 位宽 信号名 深度&#xff1b;2.变量类型 &#xff08;1&#xff09;说明&#xff1a; systemverilog中的信号类型主要分为线网类型&#xff08;wire&a…

camera和lidar外参标定

雷达和相机的外参标定&#xff08;外部参数标定&#xff09;指的是确定两者之间的旋转和平移关系&#xff0c;使得它们的坐标系可以对齐。 文章目录 无目标标定livox_camera_calibdirect_visual_lidar_calibration 有目标标定velo2cam_calibration 无目标标定 livox_camera_ca…

照片不完整?来试试智能扩图,简直不要太满意!(不是广告)

生活中有些照片拍过之后&#xff0c;当时觉得很满意&#xff0c;但过段时间就恨当初没有拍一张完整的图片&#xff01; ——来自小白的感慨 当时跟家里的叮当一起去旅游&#xff0c;我给他拍了一张好看的照片&#xff1a; 今天这张照片如果是整图就好了&#xff01;好气哦&am…

在银河麒麟系统中Qt连接达梦数据库

解决在银河麒麟系统中使用Qt连接达梦数据库提示&#xff1a;project Error library odbc is not defined问题 一、编译ODBC 下载解压unixODBC&#xff08;http://www.unixodbc.org/unixODBC-2.3.1.tar.gz&#xff09; 打开终端&#xff0c;切换到unixODBC-2.3.1目录下&#x…

【WebDriver】浏览器驱动下载及其配置

一、Windows电脑环境搭建-Chrome浏览器 行业内&#xff0c;Chrome (谷歌) 浏览器对于自动化程序来讲是比较稳定的. 自动化程序推荐使用 Chrome 浏览器的原因有几个&#xff1a; 开发者工具&#xff1a;Chrome 提供强大的开发者工具&#xff0c;方便调试和测试自动化脚本。 稳…

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解

时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解 目录 时序分解 | TTNRBO-VMD改进牛顿-拉夫逊算法优化变分模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 (创新独家)TTNRBO-VMD改进牛顿-拉夫逊优化算优化变分模态分解TTNRBO–VMD 优化VMD分解层数K和…

深度图和RGB图对齐

坐标系间的转换_坐标系转换-CSDN博客 深度图与彩色图的配准与对齐_彩色 深度 配准-CSDN博客 kinect 2.0 SDK学习笔记&#xff08;四&#xff09;--深度图与彩色图对齐_mapdepthframetocolorspace-CSDN博客 相机标定&#xff08;三&#xff09;-相机成像模型_相机小孔成像模型…

天润融通突破AI客服局限,三大关键提升文本机器人问答效果

近期&#xff0c;AI客服再次登上热搜&#xff0c;引发网友集体吐槽&#xff0c;比如AI客服虽然态度客气&#xff0c;但听不懂客户诉求&#xff0c;回答问题驴唇不对马嘴&#xff0c;解决不了问题...... 更有网友将这些问题升级到&#xff0c;企业就是不想解决问题才交给AI客服…