MyBatis:查询与连接池

一、查询

1、多表查询

尽量避免使用多表查询,尤其是对性能要求较高的项目。因为多表查询必然会导致性能变低。

例如:select *from ta运行需要10ms,select *from tb 运行也需要10s。但是,select *from ta left join tb on ta.xx==tb.xx 必然大于10ms,

并且数据库集群是很多项目一起使用的,当出现慢查询时,会影响整个集群,也就是会影响其他服务的速度。

在数据库上再建立一个文章表:

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 CURRENT_TIMESTAMP,update_time DATETIME DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARSET = 'utf8mb4';INSERT INTO articleinfo (title, content, uid) VALUES ('Java', 'Java正文', 1);
INSERT INTO articleinfo (title, content, uid) VALUES ('Python', 'Python正文', 2);

对应Model层的实体类:

package com.example.mybatisdemo.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;
}

根据uid查询作者的名称等相关信息,进行多表查询的sql语句应该为:

SELECT ta.*, tb.username
FROM articleinfo ta
LEFT JOIN userinfo tb ON ta.uid = tb.id
WHERE ta.id = 1;

所以,我们要补充实体类,在刚刚的ArticleInfo类中加入用户相关信息,便于映射:

@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;
}

对应的ArticlenInfoMapper接口:

@Mapper
public interface ArticlenInfoMapper {//多表查询@Select("select ta.*,tb.username from articleinfo ta " +"left join userinfo tb on ta.uid = tb.id " +"where ta.id = #{articleId}")ArticleInfo selectArticlenAndUserByID(Integer articleId);
}

如果名称不⼀致的,采⽤ResultMap,或者别名的方式解决, 和单表查询⼀样。Mybatis 不管单表还是多表,主要就是三部分:SQL, 映射关系和实体类通过映射关系,把SQL运⾏结果和实体类关联起来。

2、#{} 和 ${}

Ⅰ、区别

#{}和${}都是MyBatis框架中使用的占位符。

@Select("select username, `password`, age, gender, phone from userinfo where username= #{name} ")
UserInfo selectByName(String name);

image-20240319102440963

然后把#{}换成${}

@Select("select username, `password`, age, gender, phone from userinfo where username= ${name} ")
UserInfo selectByName(String name);

image-20240319102604288

使用${}时,MyBatis不会自动添加引号。{}用于直接替换SQL语句中的文本,因此在某些情况下,如果替换的值是字符串,则需要手动添加引号。

#{}利用预编译SQL的方式工作,它通过在SQL语句中使用?占位符来提前编译SQL命令,并在执行时将参数值安全地绑定到这些占位符上。MyBatis会根据参数的类型自动添加必要的引号,例如字符串类型的参数会被加上引号'',以确保SQL语句的正确性和安全性。相反,${}则采用简单的字符串替换机制,它在SQL语句编译之前直接将参数值替换到SQL命令中。这意味着如果参数值是字符串,需要手动添加引号''来确保SQL语句的语法正确性。

总结:

#{}${}在MyBatis中的区别主要体现在以下几个方面:

  1. 预编译处理
    • #{}:使用预编译语句(PreparedStatement),参数会被替换为?,并在SQL执行时绑定参数值。这种方式可以防止SQL注入,因为参数值会被数据库引擎视为数据,而不是SQL命令的一部分。
    • ${}:不使用预编译语句,参数值会直接替换到SQL语句中。这种方式不会防止SQL注入,因为参数值被视为SQL语句的一部分,如果参数值中包含SQL关键字或特殊字符,可能会改变原SQL语句的结构。
  2. 参数替换方式
    • #{}:参数替换后,MyBatis会根据参数的类型自动添加引号,例如字符串类型的参数会被加上引号''
    • ${}:参数替换后,不会自动添加引号,如果参数是字符串类型,需要手动添加引号。
  3. 使用场景
    • #{}:适用于大部分情况,尤其是处理用户输入或不可信数据时,提供安全保障。
    • ${}:适用于需要动态指定表名、列名或其他SQL关键字的情况,但使用时需要确保参数值的安全性。
  4. 性能影响
    • #{}:通常不会对性能产生负面影响,因为预编译语句可以被数据库缓存和重用。
    • ${}:如果用于字符串替换,可能会导致数据库无法有效缓存执行计划,从而影响性能。
  5. 安全性
    • #{}:提供了更好的安全性,可以防止SQL注入攻击。
    • ${}:存在SQL注入的风险,应该尽量避免使用,或者在确保参数值安全的情况下谨慎使用。

Ⅱ、SQL注入

${}存在一个非常大的问题,那就是SQL注入。当使用${}时,MyBatis不会对替换的参数值进行任何转义或预处理。这意味着,如果参数值包含特殊字符或SQL关键字,它们将直接插入到SQL语句中。如果这些值来自于用户的输入,且没有得到适当的验证和清理,攻击者就可以利用这一点来执行恶意SQL代码。

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

测试代码:

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

image-20240319112222814

SQL注⼊代码: ' or 1='1。这里可以看见,结果被正确查询出来了, 其中参数 or 被当做了SQL语句的⼀部分。由于没有对用户输⼊进行充分检查,而SQL⼜是拼接⽽成,在用户输⼊参数时,在参数中添加⼀些SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击。

3、排序查询

@Select("SELECT id, username, age, gender, phone, delete_flag, create_time, update_time " +"FROM userinfo " +"ORDER BY id ${sort}")
List<UserInfo> selectAllUserBySort(String sort);

这里使用 ${sort} 可以实现排序查询,而使用#{sort} 就不能实现排序查询。因为,此处 sort 参数为String类型,但是SQL语句中,排序规则是不需要加引号 '' 的,所以此时的${sort} 也不加引号。如果此时,使用 #{sort} 查询时, sort参数前后会自动给加了引号, 导致出现 sql 错误。

4、模糊查询

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

和前面的排序查询一样,在这个查询中,由于#{}的工作方式,MyBatis会把'%#{key}%'当作一个整体,所以 '%#{key}%' 的预期结果是,参数key被包围在两个%通配符之间。所以,当使用like查询的时候,应该使用${},但是这样又会出现SQL注入的安全问题。

为了解决这个问题,可以使用MySQL 的CONCAT函数来动态地构造like查询的参数,像这样:

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

CONCAT是MySQL中的一个函数,用于将两个或多个字符串连接在一起。

基本的语法:CONCAT(string1, string2, ..., string_n)

like查询中,你可以使用CONCAT函数来动态地构造查询参数。例如,以下查询将查找用户名包含关键词"John"的所有用户:

SELECT * FROM user WHERE username LIKE CONCAT('%', 'John', '%');

在这个例子中,CONCAT('%', 'John', '%')将返回字符串"%John%“,这将在任意位置匹配关键词"John”。

二、数据库连接池

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

image-20240319124043111

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

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

目前比较流行的是:Hikari,Druid

  1. Hikari : SpringBoot默认使用的数据库连接池
  2. Druid:阿里巴巴开源的数据库连接池

如果想把默认的数据库连接池从Hikari连接池切换为Druid连接池, 只需要在pom.xml中引入相关依赖即可

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version>
</dependency>

学习文档:常见问题 · alibaba/druid Wiki (github.com)

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

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

相关文章

python初级第一次作业

一、 dayint(input("enter today day")) fdayint(input("enter num of day since today")) c((fday%7)day)%7 if c0:print("sunday") elif c1:print("monday") elif c2:print("tuesday") elif c3:print("wendnsday&quo…

Jmeter脚本优化——CSV数据驱动文件

使用 CSV 数据文件设置实现参数化注册 1&#xff09; 本地创建 csv 文件&#xff0c;并准备要使用的数据&#xff0c;这里要参数化的是注册的用户名和邮箱。所以在 csv 文件中输入多组用户名和邮箱。 2&#xff09; 通过测试计划或者线程组的右键添加->配置元件->CSV…

多线程合并练习题,线程安全(售票任务引入)--学习JavaEE的day30

day30 练习&#xff08;day29&#xff09; 注意代码注释&#xff0c;里面涉及代码实现遇到问题及解决方案&#xff0c;由于理解方便没有单独出来 1.计算任务 1.计算任务&#xff0c;一个包含了2万个整数的数组&#xff0c;分拆了多个线程来进行并行计算&#xff0c;最后汇总出…

FT232RL/FT232RNL替代GP232RNL USB转UART桥接控制器芯片低成本方案

关注过小编的朋友都知道&#xff0c;之前小编有推荐过FT232RL的替代产品GP232RL&#xff0c;软硬件直接兼容&#xff0c;无需做修改。随着产品的更新迭代&#xff0c;后面也出来了升级版GP232RNL&#xff0c;低成本方案&#xff0c;可直接替代FT232RL/FT232RNL&#xff0c;参数…

【数据结构】线性表的定义与基本操作

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;数据结构 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

阿里二面:谈谈ThreadLocal的内存泄漏问题?问麻了。。。。

引言 ThreadLocal在Java多线程编程中扮演着重要的角色&#xff0c;它提供了一种线程局部存储机制&#xff0c;允许每个线程拥有独立的变量副本&#xff0c;从而有效地避免了线程间的数据共享冲突。ThreadLocal的主要用途在于&#xff0c;当需要为每个线程维护一个独立的上下文…

linux之sed编辑器指令练习

目录 一、sed编辑器 二、sed使用案例 1.1 s命令&#xff08;substitute替换&#xff09; 一、sed编辑器 sed编辑器比交互式编辑器快的多&#xff0c;可以简化数据处理任务,sed编辑器并不会修改文件&#xff0c;只会将修改后的数据&#xff0c;输出。 二、sed使用案例 首先…

RK3568平台 iperf3测试网络性能

一.iperf3简介 iperf是一款开源的网络性能测试工具&#xff0c;主要用于测量TCP和UDP带宽性能。它可以在不同的操作系统上运行&#xff0c;包括Windows、Linux、macOS等。iperf具有简单易用、功能强大、高度可配置等特点&#xff0c;广泛应用于网络性能测试、网络故障诊断和网…

【编译tingsboard】出现gradle-maven-plugin:1.0.11:invoke (default)

出现的错误&#xff1a; [ERROR] Failed to execute goal org.thingsboard:gradle-maven-plugin:1.0.11:invoke (default) on project http: Execution default of goal org.thingsboard:gradle-maven-plugin:1.0.11:invoke failed: Plugin org.thingsboard:gradle-maven-plugi…

mysql - 缓存

缓存 InnoDB存储引擎在处理客户端的请求时&#xff0c;当需要访问某个页的数据时&#xff0c;就会把完整的页的数据全部加载到内存中&#xff0c;也就是说即使我们只需要访问一个页的一条记录&#xff0c;那也需要先把整个页的数据加载到内存中。将整个页加载到内存中后就可以…

力扣hot100:207. 课程表

这是一道拓扑排序问题&#xff0c;也可以使用DFS判断图中是否存在环。详情请见&#xff1a;官方的BFS算法请忽略&#xff0c;BFS将问题的实际意义给模糊了&#xff0c;不如用普通拓扑排序思想。 数据结构&#xff1a;图的拓扑排序与关键路径 拓扑排序&#xff1a; class Sol…

交换机高级-端口安全

端口安全 1、一旦接口开启端口安全功能&#xff0c;那么接口所学到的动态MAC就会转换成安全MAC地址&#xff1b; 2、安全MAC地址默认情况下只能学习1个&#xff0c;可以通过命令手动修改学习数量&#xff1b; 3、安全MAC地址没有老化时间&#xff08;但是依然存在内存中&…

2核4g服务器能支持多少人访问?阿里云2核4g服务器在线人数

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

技术周刊 117 期:Visual Copilot、INP、Kimi 支持 200 万字上下文、Grok 开源、Figure 01、Open Sora 开源

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;金骏眉 大家好&#xff0c;我是童欧巴。老规矩&#xff0c;咱们先来看技术资讯。 技术资讯 前端 VitePress (早就应该) 1.0 发布MistCSS&#xff0c;只使用 CSS 来…

聚观早报 | 滴滴2023年Q4营收;微软推广Copilot

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 3月25日消息 滴滴2023年Q4营收 微软推广Copilot 极狐汽车将出口西班牙 华为公开智能驾驶新专利 华为P70系列发布…

Luminar Neo:重塑图像编辑新纪元,Mac与Win双平台畅享创意之旅

在数字时代的浪潮中&#xff0c;图像编辑软件已成为摄影师和设计师们不可或缺的创作工具。Luminar Neo&#xff0c;作为一款专为Mac与Windows双平台打造的图像编辑软件&#xff0c;正以其卓越的性能和创新的编辑功能&#xff0c;引领着图像编辑的新潮流。 Luminar Neo不仅继承…

基于nodejs+vue基于hive旅游数据的分析与应用python-flask-django-php

系统阐述的是使用基于hive旅游数据的分析与应用系统&#xff0c;对于nodejs结构、MySql进行了较为深入的学习与应用。主要针对系统的设计&#xff0c;描述&#xff0c;实现和分析与测试方面来表明开发的过程。开发中使用了express框架和MySql数据库技术搭建系统的整体架构。利用…

Kubernetes概念:服务、负载均衡和联网:2. Gateway API

Gateway API 官方文档&#xff1a;https://kubernetes.io/zh-cn/docs/concepts/services-networking/gateway/ Gateway API 通过使用可扩展的、角色导向的、 协议感知的配置机制来提供网络服务。它是一个附加组件&#xff0c; 包含可提供动态基础设施配置和高级流量路由的 API…

vscode添加gitee

1.创建仓库 2.Git 全局设置 3.初始化仓库 2.1 打开vscode打开需要上传到给git的代码文件 2.2.点击左边菜单第三个的源代码管理->初始化仓库 4.点击加号暂存所有更改 5.添加远程仓库 5.1 添加地址&#xff0c;回车 5.2 填写库名&#xff0c;回车 6.提交和推送 6.1 点击✔提交…

Matlab|基于模型预测控制(MPC)的微电网调度优化的研究

目录 1 主要内容 2 程序难点及问题说明 3 部分程序 4 下载链接 1 主要内容 该程序分为两部分&#xff0c;日前优化部分——该程序首先根据《电力系统云储能研究框架与基础模型》上面方法&#xff0c;根据每个居民的实际需要得到响应储能充放电功率&#xff0c;优化得到整…