【MyBatis】(MyBatis 其他查询操作 多表查询 #{} 和 ${} 排序功能 like 查询 #{} 和 ${} 的区别 数据库连接池)

news2024/11/16 3:28:35

文章目录

  • MyBatis
    • 其他查询操作
      • 多表查询
      • #{} 和 ${}
      • 排序功能
      • like 查询
      • #{} 和 ${} 的区别
    • 数据库连接池


MyBatis

其他查询操作

创建表:

-- 创建⽂章表
DROP TABLE IF EXISTS articleinfo;
CREATE TABLE articleinfo (
 id INT PRIMARY KEY auto_increment,
 title VARCHAR ( 100 ) NOT NULL,
 content TEXT NOT NULL,
 uid INT NOT NULL,
 delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
 create_time DATETIME DEFAULT now(),
 update_time DATETIME DEFAULT now() 
) DEFAULT charset 'utf8mb4';
-- 插⼊测试数据
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正⽂', 1
);

在这里插入图片描述

在这里插入图片描述

多表查询

对应model

SQL中直接查询多个表,把查询的结果放在一个对象即可。

package com.example.demo.model;

import lombok.Data;


import java.util.Date;

@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
    //用户相关信息
    private String username;
    private Integer age;
}

SQL

select ta.*, tb.username,tb.age from articleinfo ta 
left join userinfo tb on ta.uid = tb.id 
where ta.id = 1

这是一个拼接的SQL查询语句,用于从两个数据表articleinfouserinfo中检索数据。下面是对这个查询语句的逐步解释:

  1. 选择字段:
select ta.*, tb.username, tb.age

这部分表示选择articleinfo表中的所有字段(ta.*),以及userinfo表中的usernameage字段。tatb是这两个表的别名,用于简化后续的查询。

  1. 连接表:
from articleinfo ta  
left join userinfo tb on ta.uid = tb.id

这里使用左连接(left join)将articleinfo表(别名为ta)和userinfo表(别名为tb)连接在一起。连接的条件是articleinfo表中的uid字段等于userinfo表中的id字段。左连接意味着即使userinfo表中没有与articleinfo表匹配的记录,articleinfo表中的记录仍然会被选择出来,但userinfo表的字段将为NULL

  1. 筛选条件:
where ta.id = 1

这部分是查询的筛选条件,它指定只选择那些articleinfo表中id字段等于1的记录。

所以,整个查询的意思是:articleinfo表中选择id为1的记录,并左连接userinfo表,获取与articleinfo表中uid字段相匹配的userinfo表中的usernameage字段。如果没有匹配的userinfo记录,这些字段将为NULL

注意:在拼接SQL语句时,应该小心处理字符串的连接,以避免SQL注入等安全问题。在实际应用中,推荐使用预编译的SQL语句来确保安全。此外,SQL语句的拼接最好使用空格或其他适当的分隔符,以确保生成的SQL语法正确。在这个例子中,虽然拼接看起来是连续的,但在实际编程中,可能需要确保字符串连接后没有多余的空格或缺少必要的空格。

/**
 * 多表查询
 * @param articleId
 * @return
 */
@Select("select ta.*, tb.username,tb.age from articleinfo ta" +
        " left join userinfo tb on ta.uid = tb.id" +
        " where ta.id = 1")
ArticleInfo selectArticleAndUserById(Integer articleId);

测试用例:

@Test
void selectArticleAndUserById() {
    ArticleInfo articleInfo = articleInfoMapper.selectArticleAndUserById(1);
    log.info(articleInfo.toString());
}

在这里插入图片描述

#{} 和 ${}

使用#{}查询:

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where id= #{id}")
UserInfo selectOne(Integer id);

在这里插入图片描述
使用${}查询:

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where id= ${id}")
UserInfo selectOne(Integer id);

在这里插入图片描述
在这里插入图片描述

看下面的例子:

使用#{}查询(通过username):

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where username= #{username}")
UserInfo selectByName(String username);

查询:

@Test
void selectByName() {
    log.info(userInfoMapper.selectByName("admin").toString());
}

在这里插入图片描述
使用${}查询(通过username):

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where username= ${username}")
UserInfo selectByName(String username);

查询:

@Test
void selectByName() {
    log.info(userInfoMapper.selectByName("admin").toString());
}

在这里插入图片描述
程序直接报错了,若想要正确运行,需要给${username}处加单引号。

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where username= '${username}'")
UserInfo selectByName(String username);

在这里插入图片描述
此时就可以运行成功了。

在这里插入图片描述

使用#{}时,如果参数为String,会自动加上'',而 ${}不会,${}符号是直接拼接,如果是字符串类型,需要加上''

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

正常的sql:

select * from userinfo where username= 'admin'

sql 注⼊代码: ' or 1='1

 select * from userinfo where username ='' or 1='1';

在这里插入图片描述
select * from userinfo where username ='' or 1='1'; 这条SQL查询语句存在严重的安全风险,是一个典型的SQL注入示例。这条语句试图从userinfo表中选择所有记录,无论username字段的值是什么。

解释如下:

  1. select * from userinfo:这部分表示从userinfo表中选择所有字段。

  2. where username ='':这部分是查询的条件,原本意图是选择username字段为空字符串的记录。

  3. or 1='1':这部分是问题的关键。or表示逻辑或,1='1'是一个恒真的条件(因为1永远等于1)。因此,不论username字段的值是什么,只要or 1='1'这一部分存在,整个查询都会返回userinfo表中的所有记录。

SQL注入的例子:

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where username= '${username}'")
List<UserInfo> selectByName(String username);

测试:

    @Test
    void selectByName() {
        log.info(userInfoMapper.selectByName("' or 1='1").toString());
    }

在这里插入图片描述

我们发现数据居然查询出来了,这就验证了sql注入的问题。

在这里插入图片描述
使用#{}查询:

@ResultMap(value = "BaseMap")
@Select("select * from userinfo where username= #{username}")
List<UserInfo> selectByName(String username);

测试;

@Test
void selectByName() {
    log.info(userInfoMapper.selectByName("' or 1='1").toString());
}

查出来结果是0
在这里插入图片描述

排序功能

进行一个升序查询:

/**
 *
 * @param sort
 * @return
 */
@Select("select * from userinfo order by id  #{sort}")
List<UserInfo> selectUserSort(String sort);
@Test
void selectUserSort() {
    log.info(userInfoMapper.selectUserSort("asc").toString());
}

在这里插入图片描述

#{sort}MyBatis中是用来绑定参数值的,而不是直接拼接到SQL语句中的。如果这样写,MyBatis会尝试将sort作为一个参数的值去绑定,而不是将其当作SQL语句的一部分

正确的做法是使用${}来直接插入变量到SQL语句中。

/**
 *
 * @param sort
 * @return
 */
@Select("select * from userinfo order by id  ${sort}")
List<UserInfo> selectUserSort(String sort);

注意,这样做会有SQL注入的风险,因为${}中的内容是直接拼接到SQL语句中的,不会经过MyBatis的预编译处理。如果sort变量来自不可信的来源,那么这可能会引发安全问题。

如果信任sort变量的来源(例如,它只来自一个固定的枚举或已知的安全值集合),可以这样写:

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

在上面的代码中,@Param("sort")注解用来指定传递给SQL的参数名称,这样MyBatis就知道sort变量是对应到SQL语句中的${sort}部分的。

like 查询

like 使⽤ #{} 报错

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +
 "from userinfo where username like '%#{key}%' ")
List<UserInfo> queryAllUserByLike(String key);

在这里插入图片描述

#{} 改成 ${} 可以正确查出来,

@Select("select * from userinfo where username like '%${username}%'")
List<UserInfo> selectUserByLike(String username);

在这里插入图片描述

@Test
void selectUserByLike() {
    log.info(userInfoMapper.selectUserByLike("java").toString());
}

但是${}存在SQL注⼊的问题, 所以不能直接使⽤${}.

解决办法: 使⽤ mysql 的内置函数 concat() 来处理:

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +
 "from userinfo where username like concat('%',#{key},'%')")
List<UserInfo> queryAllUserByLike(String key);

#{} 和 ${} 的区别

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

1. 预编译SQL#{} 性能更高。

在这里插入图片描述

大多数情况下, 某⼀条 SQL 语句可能会被反复调用执行, 或者每次执⾏的时候只有个别的值不同(比如selectwhere⼦句值不同, updateset 子句值不同, insertvalues 值不同). 如果每次都需要经过上⾯的语法解析, SQL优化、SQL编译等,则效率就明显不行了

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

2. 预编译SQL${}不存在SQL注入的问题。

3. 排序时不能使用#{},表名,字段名等作为参数时,也不能使用#{}

4. 模糊查询时,如果使用#{},需要搭配mysql的内置函数concat,而不能直接使用。

数据库连接池

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

在这里插入图片描述

没有使⽤数据库连接池的情况: 每次执行SQL语句, 要先创建⼀个新的连接对象, 然后执⾏SQL语句, SQL语句执行完, 再关闭连接对象释放资源. 这种重复的创建连接, 销毁连接比较消耗资源。
使用数据库连接池的情况: 程序启动时, 会在数据库连接池中创建⼀定数量的Connection对象, 当客户请求数据库连接池, 会从数据库连接池中获取Connection对象, 然后执行SQL, SQL语句执⾏完, 再把Connection归还给连接池。

常见的数据库连接池:

  1. C3P0
  2. DBCP
  3. Druid
  4. Hikari

目前比较流⾏的是 Hikari, Druid

  1. Hikari
    SpringBoot默认使⽤的数据库连接池就是Hikari
    在这里插入图片描述
  2. Druid
    切换为Druid数据库连接池, 只需要引⼊相关依赖即可
<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid-spring-boot-starter</artifactId>
 <version>1.1.17</version>
</dependency>

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

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

相关文章

2024/4/19学习笔记 vector模拟实现(2)

本次学习重点 1.迭代器区间构造和size_t n 构造 2.string扩容问题 3.erase的缺陷 1.迭代器区间构造和size_t n 构造 vector支持用一段迭代器区间构造&#xff0c;也可以支持任意类型的迭代器区间&#xff0c;所以要写成函数模板 template <class InputIterator> ve…

SL7220线性降压恒流3.6A 外围只需两个电阻 耐压40V汽车大灯IC

概述&#xff1a; SL7220 是一款双路线性降压LED恒流驱动器&#xff0c;外围只需两个电阻&#xff0c;输出电流10MA-3600MA。 SL7220 内置过热保护功能&#xff0c;内置输入过压保护功能。 SL7220 静态电流典型值为120uA。 特点 ●输入电压范围&#xff1a;2.5V-40V ●电…

浅识数据结构之时间复杂度

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 文章目录 前言一. 时间复杂度1.1 时间复杂度的概念1.2 时间复杂度如何计算1.3 时间复杂度如何表…

谷歌地球引擎Google Earth Engine下载数字高程模型DEM数据的方法

本文介绍在谷歌地球引擎&#xff08;Google Earth Engine&#xff0c;GEE&#xff09;中&#xff0c;批量下载指定时间与空间范围内的数字高程模型&#xff08;DEM&#xff09;数据的方法。 本文是谷歌地球引擎&#xff08;Google Earth Engine&#xff0c;GEE&#xff09;系列…

c语言中的数组

数组 数组是一种构造类型&#xff0c;是由基本类型构造而成。当我们想用一群变量来描述同一类相同的东西时候&#xff0c;比如100个年龄变量&#xff0c;我们可以这样int age1&#xff1b;int age2&#xff1b;int age3&#xff1b;……int age 100;这样即不方便书写&#xff…

GPU异构内存管理

通过异构内存管理简化 GPU 应用程序开发 异构内存管理 (HMM) 是一项 CUDA 内存管理功能&#xff0c;它扩展了 CUDA 统一内存编程模型的简单性和生产力&#xff0c;以包括具有 PCIe 连接的 NVIDIA GPU 的系统上的系统分配内存。 系统分配内存是指最终由操作系统分配的内存&#…

深入理解MD5:Message Digest Algorithm 5

title: 深入理解MD5&#xff1a;Message Digest Algorithm 5 date: 2024/4/21 18:10:18 updated: 2024/4/21 18:10:18 tags: MD5哈希函数密码学数据完整性碰撞攻击安全性替代算法 导论 MD5的背景和历史 MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种广泛使用…

Axure引用ECharts图表 解决火狐浏览器出错

Axure原型添加Echarts图表&#xff0c;没耐心看文章的可以直接下载示例 Axure中使用ECharts图表示例 1. 打开Axure新建页面 2. 页面添加元件 元件类型随意&#xff0c;矩形、动态面板、热区、图片 甚至段落都可以3. 命名元件 随意命名&#xff0c;单个页面用到多个图表时名…

dspbuilder中使用signalcompiler时报错Error during compilation: Fitter failed,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

安装IntelliJ IDEA

文章目录 一、前言二、下载IDEA三、安装四、破解 一、前言 工欲善其事必先利其器&#xff0c;学习JAVA的第一步&#xff0c;首先是安装IDE&#xff0c;配置环境&#xff1b; 常用的JAVA IDE是IntelliJ IDEA和eclipse&#xff0c;我选择IntelliJ IDEA 二、下载IDEA 官网下载&…

游戏测试之常见控制技能(下)

备注&#xff1a;未经博主允许禁止转载 个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_w…

C++11 数据结构5 队列的概念,队列的顺序存储,实现,测试

一&#xff0c;队列的概念 队列是一种特殊的受限制的线性表。 队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&#xff0c;而在另一端进行删除操作的线性表。 队列是一种先进先出的t&#xff08;First In First Out&#xff09;的线性表&#xff0c;简称FIF…

数据库管理-第171期 Oracle是用这种方式确保读一致的(20240418)

数据库管理171期 2024-04-18 数据库管理-第171期 Oracle是用这种方式确保读一致的&#xff08;20240418&#xff09;1 基本概念2 用处3 注意事项总结 数据库管理-第171期 Oracle是用这种方式确保读一致的&#xff08;20240418&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#x…

Redis系列之哨兵Sentinel集群搭建

在上一篇博客&#xff0c;我们已经知道怎么搭建一个redis主从复制集群&#xff0c;但是主从集群如果出现服务器宕机的情况&#xff0c;是不会自动选举master的&#xff0c;所以需要搭建更加高可用的集群模式&#xff0c;哨兵模式&#xff0c;哨兵集群会自动监控&#xff0c;如果…

深度学习发展中的继承和创新

深度学习是一步一步发展而来的&#xff0c;新的成就也是在原有的基础上&#xff0c;逐步取得突破&#xff0c;有一些东西是一点一点变化&#xff0c;突破发展而来的&#xff0c;也就是每一次小的突破和每一次小的突破累积起来&#xff0c;构成一个明显的进步。我们可以通过观察…

python 文件 成绩分析2

‘’’ 文件score.txt中存储了学生的考试信息,内容如下 小明,98,96 小刚,90,94 小红,90,94 小王,98,96 小刘,80,90 小赵,90,96 第二列是数学成绩&#xff0c;第三列是语文成绩 请写程序分析&#xff1a; 哪些同学语文成绩是相同的?哪些同学数学成绩是相同的?哪些同学语文和数…

C语言—字符指针,指针数组和数组指针详解

字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* ; int main() {char ch w;char *pc &ch;*pc w;return 0; }还有一种使用方式如下&#xff1a; int main() {const char* pstr "hello world.";//这里是把一个字符串放到pstr指针变量里了吗…

WebSocket 快速入门 - springboo聊天功能

目录 一、概述 1、HTTP&#xff08;超文本传输协议&#xff09; 2、轮询和长轮询 3、WebSocket 二、WebSocket快速使用 1、基于Java注解实现WebSocket服务器端 2、JS前端测试 三、WebSocket进阶使用 1、如何获取当前用户信息 2、 后端聊天功能实现 一、概述 HTTP…

Linux安装Docker完整教程及配置阿里云镜像源

官网文档地址 安装方法 1、查看服务器内核版本 Docker要求CentOS系统的内核版本高于3.10 uname -r #通过 uname -r 命令查看你当前的内核版本2、首先卸载已安装的Docker&#xff08;如果有&#xff09; 2.1 确保yum包更新到最新 yum update2.2 清除原有的docker&#xff0c…

生物特征识别的六大技术研究

生物特征识别技术是结合了计算机科学与光学、声学、生物传感器以及生物统计学原理&#xff0c;通过利用人体固有的生理特征&#xff08;如指纹、人脸、虹膜、掌纹、指静脉等&#xff09;和行为特征&#xff08;如笔迹、声音、步态等&#xff09;&#xff0c;来进行个人身份的鉴…