文章目录
- 一、MySQL8解压版安装指南
- 二、MySQL忘记密码的处理措施
- 三、JDBC相关注意点
-
- [1. SQL 注入](#1. SQL 注入)
- 2.连接池
-
- [1. 连接池的作用](#1. 连接池的作用)
-
- [1.1 减少连接创建的开销](#1.1 减少连接创建的开销)
- [1.2 提升性能](#1.2 提升性能)
- [1.3 控制连接数量](#1.3 控制连接数量)
- [1.4 管理连接资源](#1.4 管理连接资源)
- [1.5 增强系统的可伸缩性](#1.5 增强系统的可伸缩性)
- [1.6 自动回收资源](#1.6 自动回收资源)
- 2.连接池的典型实现
- [3. JDBC代码封装的意义](#3. JDBC代码封装的意义)
-
- [3.1 提高代码的复用性](#3.1 提高代码的复用性)
- [3.2 简化代码逻辑](#3.2 简化代码逻辑)
- [3.3 统一异常处理](#3.3 统一异常处理)
- [3.4 提高可扩展性](#3.4 提高可扩展性)
- [3.5 支持事务管理](#3.5 支持事务管理)
- [3.6 增强代码的可测试性](#3.6 增强代码的可测试性)
- [3.7 增加安全性](#3.7 增加安全性)
- [四 JDBC模板](#四 JDBC模板)
-
- 1.JDBC连接池的选择
-
- [1.1.为什么选择 HikariCP?](#1.1.为什么选择 HikariCP?)
- [2.2.HikariCP 的核心特性](#2.2.HikariCP 的核心特性)
- [2.如何在 Java 应用中使用 HikariCP](#2.如何在 Java 应用中使用 HikariCP)
-
- [2.1. 添加依赖](#2.1. 添加依赖)
- [2.2. 基本配置](#2.2. 基本配置)
- [2.3.Spring Boot 集成 HikariCP](#2.3.Spring Boot 集成 HikariCP)
- 2.4.HikariCP总结
- 2.5.JDBC总结
- 五、Spring和JDBC
-
- [1. Spring 和 JDBC 的关系](#1. Spring 和 JDBC 的关系)
- [2. 为什么仍然需要了解 JDBC](#2. 为什么仍然需要了解 JDBC)
-
- [2.1 理解底层原理](#2.1 理解底层原理)
- [2.2 数据库操作的灵活性](#2.2 数据库操作的灵活性)
- [2.3 更细粒度的控制](#2.3 更细粒度的控制)
- [2.4 其他框架或技术栈的需求](#2.4 其他框架或技术栈的需求)
- [3. 什么时候不需要过多关注 JDBC](#3. 什么时候不需要过多关注 JDBC)
- [4. 总结:学完 Spring 之后是否需要继续学习 JDBC?](#4. 总结:学完 Spring 之后是否需要继续学习 JDBC?)
- [5. 推荐的学习路径](#5. 推荐的学习路径)
- 六、MySQL思考题
一、MySQL8解压版安装指南
- 下载 mysql8的压缩版文件, 官网地址:点击进入官网下载
- 解压文件至指定的目录中
- 在解压目录下创建一个名为
my.ini的文件, 内容如下:
ini
[mysqld]
# 设置3306端口
port=3306
# 自定义设置mysql的安装目录,即解压mysql压缩包的目录
basedir=D:\database\mysql-8.0.17-winx64
# 自定义设置mysql数据库的数据存放目录
datadir=D:\database\mysqlDATA
# 允许最大连接数
max_connections=200
# 允许连接失败的次数,这是为了防止有人从该主机试图攻击数据库系统
max_connect_errors=10
# 服务端使用的字符集默认为UTF8
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 默认使用"mysql_native_password"插件认证
default_authentication_plugin=mysql_native_password
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[client]
# 设置mysql客户端连接服务端时默认使用的端口和默认字符集
port=3306
default-character-set=utf8
注:大小写敏感
-
配置mysql的环境变量, 如下
- 创建一个名为 MYSQL_HOME 的环境变量,指向上面解压的目录
- 在bin环境变量中,把 %MYSQL_HOME%\bin 添加进去
-
以管理员的身份运行cmd 窗口,执行如下命令
shell
1. 安装mysql的服务,执行如下命令
mysqld --install MYSQL
> 这条命令可以把MYSQL服务添加到系统服务中
> 注:如果要移除MYSQL服务,可以执行 `mysqld --remove`
2. 切换到 %MYSQL_HOME%\bin 目录下,执行
mysqld --initialize //此命令会自动生成带随机密码的root用户
或
mysqld --initialize-insecure //自动生成无密码的root用户
> 执行成后,在 datadir指向的目录中会生成一个 xxx.err 文件,
> 在这个文件中可以看到生成的随机密码
3. 启动 mysqld 服务,执行:
net start mysql
//停止mysql 服务,可以执行:
net stop mysql
4. 连接mysql服务
mysql -u root -p
> 如果生成了随机密码,则此处填写随机密码,如果没有密码,
> 则直接回车后进入
1. 重置root用户的密码
mysql> alter user 'root'@'localhost' identified with
mysql_native_password by '新密码';
> 注:如果启动服务时报错,则可以删除掉 data 文件夹,再重新执行上面的步骤
二、MySQL忘记密码的处理措施
- 在mysql的配置文件
my.ini文件中,在[mysqld]下面添加配置skip-grant-tables,跳过权限表认证 - 执行
net stop mysql停止mysql服务 - 执行
net start mysql启动mysql服务 - 执行
mysql -u root -p,直接回车后进入mysql - 登录成功后,更新密码,执行如下命令
sql
update user set authentication_string=password('新密码')
where user='root'
或:
alter user 'root'@'localhost' identified with
mysql_native_password by 'new password';
- 把
my.ini文件中的skip-grant-tables去掉 - 重新启动 mysql 即可
三、JDBC相关注意点
1. SQL 注入
SQL 注入(SQL Injection) 是一种安全漏洞,攻击者通过在输入字段中插入恶意 SQL 代码,从而操控后端数据库执行未被授权的操作。通常情况下,SQL 注入发生在应用程序未对用户输入进行适当的验证和清理时。
SQL 注入的工作原理:
- 攻击者可以在用户输入的地方(如表单、URL 参数)插入恶意 SQL 代码。
- 如果应用程序直接将这些输入拼接到 SQL 查询中,攻击者的代码就会被执行,可能导致数据泄露、数据篡改、甚至数据库的完全控制。
防止 SQL 注入的方法: - 使用 PreparedStatement 和参数化查询。
- 对用户输入进行严格的验证和清理。
- 限制数据库账户的权限,只给予必要的操作权限。
- 使用 ORM(对象关系映射)工具来处理数据库交互,降低直接执行 SQL 的风险。
通过采取这些措施,可以大大降低 SQL 注入攻击的风险。
sql注入详解
2.连接池
1. 连接池的作用
数据库连接池(Connection Pool)是一个专门用于管理数据库连接的组件,它通过复用连接来提升数据库访问性能。连接池的主要作用和优势如下:
1.1 减少连接创建的开销
每次建立数据库连接都需要消耗大量的时间和系统资源。传统的做法是每次需要数据库连接时都创建一个新连接,执行完操作后再关闭该连接。这种方式会导致频繁的连接创建和销毁,极大地浪费资源和时间,尤其在高并发的环境中会导致性能下降。
1.2 提升性能
连接池通过维护一组已建立的数据库连接,当应用程序需要连接时,从连接池中获取一个空闲连接;操作完成后将连接归还池中,而不是关闭连接。这显著减少了连接创建和销毁的时间,从而提升了系统性能。
1.3 控制连接数量
连接池通常会设置最大连接数(maxPoolSize)来控制同时建立的数据库连接数,这防止了数据库连接数过多导致数据库崩溃或性能下降的情况。连接池还可以设置最小连接数,确保一定数量的连接始终可用。
1.4 管理连接资源
连接池可以自动管理连接的生命周期。连接池可以检测到失效或超时的连接,并自动回收它们。还可以对连接进行健康检查,确保每个连接在使用时是有效的。
1.5 增强系统的可伸缩性
由于连接池能够有效管理连接数,因此能够应对高并发请求。在系统负载增加时,连接池可以通过增加连接池大小来满足需求,确保系统稳定运行。
1.6 自动回收资源
连接池能够自动处理连接的回收,减少开发者手动关闭连接的繁琐工作,并避免资源泄漏问题。
2.连接池的典型实现
- HikariCP:目前是一个非常流行的高性能数据库连接池,具备低延迟和高吞吐量的特点。
- C3P0:另一个流行的数据库连接池,它提供了许多高级配置选项。
- DBCP:由 Apache 提供的数据库连接池,实现较为简单且易于使用。
3. JDBC代码封装的意义
JDBC(Java Database Connectivity)是 Java 与数据库之间的通信协议,它通过 Connection、Statement、PreparedStatement 等对象与数据库进行交互。封装 JDBC 代码的意义主要体现在以下几个方面:
3.1 提高代码的复用性
通过封装 JDBC 代码,可以将重复的数据库操作(如建立连接、执行查询或更新、关闭资源等)抽象成通用方法或工具类。这使得代码更加模块化和易于重用。例如,JdbcTemplate 作为 Spring 框架中的工具类,就封装了多种数据库操作的模板,开发者只需要关注具体的 SQL 和数据处理逻辑。
3.2 简化代码逻辑
直接编写 JDBC 代码时,涉及到连接管理、资源关闭等操作,代码会变得复杂。封装 JDBC 操作可以将这些繁琐的操作抽象化,使得代码更加简洁,减少了错误发生的几率。例如,在 try-with-resources 的机制下,资源管理变得更加简单。
3.3 统一异常处理
JDBC 操作中可能会遇到多种异常,如 SQLException,需要在不同的地方进行异常捕获和处理。通过封装 JDBC,可以集中处理异常,避免冗余的异常处理代码,增强代码的可维护性。例如,可以通过自定义异常处理逻辑来统一捕获和处理数据库相关的异常。
3.4 提高可扩展性
通过封装 JDBC 代码,可以让数据库操作与应用程序的其他逻辑解耦。这样可以方便地替换或更改底层的数据库操作而不影响应用的业务逻辑。例如,如果换用不同的数据库(如从 MySQL 切换到 PostgreSQL),通过封装 JDBC 代码,可以减少修改的范围。
3.5 支持事务管理
JDBC 代码封装可以简化事务的管理。通过将事务管理逻辑封装到单独的模块中,可以在数据库操作开始时开启事务,在操作结束时提交或回滚事务。封装后的代码可以更加清晰和一致,减少了手动管理事务的复杂度。
3.6 增强代码的可测试性
封装后的 JDBC 操作可以方便地进行单元测试。通过将数据库操作封装到一个独立的类或方法中,测试人员可以更容易地模拟数据库交互(比如使用 Mock 或 H2 等内存数据库),而不需要在每个测试用例中编写繁琐的数据库连接和查询代码。
3.7 增加安全性
封装后的 JDBC 代码可以集中管理数据库的连接、查询、更新等操作,减少了 SQL 注入等安全漏洞的发生。比如,使用 PreparedStatement 替代 Statement,可以避免 SQL 注入攻击。
四 JDBC模板
1.JDBC连接池的选择
HikariCP 是一个高性能的 JDBC 连接池,它被设计为轻量级、高效且易于配置。它是目前最受欢迎的 Java 连接池之一,广泛应用于 Spring Boot 和其他 Java 应用程序中。HikariCP 相较于其他连接池(如 Apache DBCP 和 C3P0)在性能方面表现非常优异。
1.1.为什么选择 HikariCP?
- 性能优越:HikariCP 的设计目标就是提供更高的性能,尤其是在高并发的场景下。它通过高效的数据库连接获取、释放机制,减少了不必要的开销,保证了连接池的最大吞吐量。
- 轻量化:HikariCP 的代码库非常精简,仅包含必要的功能和配置选项,没有过多的附加功能,因此能够以最小的资源消耗提供最大性能。
- 兼容性好:它支持多种 JDBC 驱动和数据库,几乎适用于所有常见的关系型数据库。
2.2.HikariCP 的核心特性
- 快速获取连接:HikariCP 在连接池管理中使用了更高效的算法和数据结构,使得连接的获取和释放速度更快。
- 低延迟:在高并发场景下,HikariCP 的延迟非常低,连接池中的连接响应时间通常在毫秒级别。
- 支持多种数据库:兼容 MySQL、PostgreSQL、Oracle、SQL Server 等各种数据库。
- 自动回收:HikariCP 提供了自动检测并回收死连接的功能,保证了池中只会保持有效的连接。
- 优雅的关闭:在应用关闭时,HikariCP 会正确、优雅地释放资源,避免连接泄漏。
2.如何在 Java 应用中使用 HikariCP
2.1. 添加依赖
如果使用的是 Maven,首先需要在 pom.xml 中添加 HikariCP 的依赖:
xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version> <!-- 请使用最新的版本 -->
</dependency>
如果是gradle,需要在 Gradle 项目的 build.gradle文件中添加:
c
dependencies {
implementation 'com.zaxxer:HikariCP:5.0.1'
// 还需要数据库驱动,例如:
implementation 'mysql:mysql-connector-java:8.0.33'
}
2.2. 基本配置
我们可以通过程序代码或配置文件来配置 HikariCP。以下是通过代码配置 HikariCP 的基本步骤:
java
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class HikariCPExample {
public static void main(String[] args) {
// 配置连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("myuser");
config.setPassword("mypassword");
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 可选的配置项
config.setMaximumPoolSize(10); // 最大连接池大小
config.setMinimumIdle(5); // 最小空闲连接数
config.setIdleTimeout(600000); // 连接最大空闲时间
config.setMaxLifetime(1800000); // 连接的最大生命周期(30分钟)
config.setConnectionTimeout(30000); // 连接获取超时时间(30秒)
// 创建连接池
DataSource dataSource = new HikariDataSource(config);
// 通过 DataSource 获取连接
try (Connection connection = dataSource.getConnection()) {
// 使用连接进行数据库操作
System.out.println("Connection successful!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
2.3.Spring Boot 集成 HikariCP
Spring Boot 默认使用 HikariCP 作为其连接池实现。如果使用 Spring Boot,只需要在 application.properties 或 application.yml 配置文件中进行配置:
application.properties 示例:
java
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置连接池
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
application.yml 示例:
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: myuser
password: mypassword
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 10
minimum-idle: 5
idle-timeout: 600000
max-lifetime: 1800000
connection-timeout: 30000
在 Spring Boot 中,HikariCP 会自动启用,且无需显式地创建 DataSource 或 HikariDataSource 实例。Spring Boot 会使用 HikariDataSource 来管理数据库连接。
2.4.HikariCP总结
HikariCP 是一个轻量级、高性能的 JDBC 连接池,广泛应用于需要高吞吐量和低延迟的应用程序。它具有易于配置、性能优越和稳定性高的特点,在大多数 Java 项目中,尤其是使用 Spring Boot 时,都推荐使用 HikariCP 作为默认的连接池实现。通过合理的配置和优化,HikariCP 可以有效提升数据库操作的效率,并保持应用的高性能。
2.5.JDBC总结
JDBC 模板(比如 Spring JDBC Template)相比于传统的 JDBC 代码确实多了一些封装,但它所提供的优势也是显而易见的,特别是在开发和维护大规模应用程序时。Spring JDBC Template 封装了很多繁琐的细节,简化了数据库操作,避免了重复的代码,提高了代码的可维护性和可读性。
五、Spring和JDBC
1. Spring 和 JDBC 的关系
Spring 框架本身是基于 JDBC 之上的,它提供了多种更高级的数据库访问技术,最常用的包括:
- Spring JDBC Template:简化了原生 JDBC 的操作,使得开发人员可以用更简洁的方式执行数据库操作,同时处理了许多底层细节,比如连接管理、异常处理、资源关闭等。
- Spring Data JPA / Hibernate :这是 Spring 中常用的 ORM(对象关系映射) 框架,通过将数据库中的表映射为 Java 类,极大地减少了 SQL 操作,开发人员只需专注于实体类和业务逻辑。
这些 Spring 的高级特性简化了 JDBC 的使用,但它们的底层还是依赖于 JDBC 连接数据库的原理。因此,虽然 Spring 提供了更高层次的抽象,但 JDBC 是 Java 应用中与数据库交互的基础。
2. 为什么仍然需要了解 JDBC
2.1 理解底层原理
即使使用 Spring JDBC Template 或 JPA/Hibernate,了解 JDBC 的工作原理依然非常重要:
- 性能调优:一些特定的数据库操作(如批量插入、大量查询等)可能需要直接使用 JDBC 来优化性能,Spring 的高级抽象可能没有足够的灵活性来满足这些需求。
- 底层问题排查:当数据库连接、SQL 执行等出现问题时,了解 JDBC 可以帮助我们更好地排查问题和理解发生的错误。
2.2 数据库操作的灵活性
尽管 Spring 提供了强大的数据库操作工具,如 Spring Data JPA,但它们的抽象有时可能无法满足非常复杂或特殊的数据库操作需求。例如:
- 复杂的 SQL 查询:当需要写一些非常复杂的 SQL 查询或存储过程时,直接使用 JDBC 可能更为灵活。
- 数据库特定功能:有时候,某些数据库的特定功能(如窗口函数、特定的索引操作等)可能不完全通过 ORM 或 Spring 数据库抽象层支持,此时直接使用 JDBC 是必须的。
2.3 更细粒度的控制
Spring 提供的抽象层(如 JPA 、Spring JDBC Template)虽然很强大,但它们也会隐藏很多底层的细节。例如,SQL 的执行顺序、事务的提交方式等。如果需要对这些细节进行更精细的控制,直接使用 JDBC 可能会更加灵活。
2.4 其他框架或技术栈的需求
有些轻量级的框架或者项目可能不依赖于 Spring 或 ORM 技术。在这些情况下,直接使用 JDBC 是唯一的选择。例如:
- 小型的项目或者微服务架构中的某些服务可能更倾向于使用直接的 JDBC 操作。
- 某些场景下可能需要 JDBC 来执行特定的查询或数据库操作,而使用 ORM 框架可能导致不必要的复杂性或性能问题。
3. 什么时候不需要过多关注 JDBC
在大多数应用中,尤其是使用 Spring 和 ORM 框架(如 JPA、Hibernate)的时候,大部分时间会通过 Spring JDBC Template 或 Spring Data JPA 来进行数据库操作。在这种情况下,通常不需要直接编写 JDBC 代码,因为 Spring 提供了高度抽象的接口来进行数据库交互。
- Spring Data JPA 和 Spring Data JDBC 提供了更高层次的抽象,只需编写实体类和接口,不必关心底层的 SQL 查询。
- Hibernate 作为 ORM 框架,可以自动生成和执行 SQL 查询,大大减少了对 JDBC 的直接操作需求。
4. 总结:学完 Spring 之后是否需要继续学习 JDBC?
- 需要了解 JDBC 原理:Spring 和 JPA/Hibernate 等框架的底层依赖于 JDBC,因此,理解 JDBC 的基本概念(如连接池、SQL 执行、事务管理等)对于深入理解 Spring 数据库操作、性能调优和问题排查是有帮助的。
- 使用 Spring 时不需要直接使用 JDBC :如果已经掌握了 Spring 的高级功能,如
JdbcTemplate或Spring Data JPA,那么大部分日常开发中可以避免直接使用 JDBC。 - 对于特殊需求或优化,可能需要用到 JDBC:当遇到一些复杂的数据库操作或性能优化的场景时,直接使用 JDBC 可能会更高效。
5. 推荐的学习路径
- 先学习 JDBC:了解 JDBC 的基本操作是必须的,尤其是在刚接触数据库时,了解如何手动进行数据库连接、查询和更新是非常有用的。
- 再深入 Spring 数据访问模块 :学习如何使用
Spring JDBC Template、Spring Data JPA等更高级的数据库抽象工具。可以不直接写 SQL,但是理解底层如何工作会帮助在开发中更高效、更容易排查问题。
总之,学完 Spring 后,我们不一定要写大量的原生 JDBC 代码,但理解 JDBC 的原理和使用场景仍然是非常有价值的。
六、MySQL思考题
题目
假设有新闻表有15列,其中10列以上有索引,现在共有500W行数据,如何快速导入,请写出处理的方案?
参考答案:为了快速导入大规模数据(如500W行)到一个有多个索引的新闻表中,以下是一个有效的处理方案:
方案概述
- 关闭索引和约束:在导入数据之前,临时关闭表中的索引和约束。
- 分批导入数据:将数据分批导入,以避免一次性导入大量数据导致的性能瓶颈。
- 恢复索引和约束:导入完成后,重新启用索引和约束,并重建索引。
- 优化数据库配置:根据需要调整数据库配置以优化导入性能。
详细步骤如下:
sql
1. 关闭索引和约束
在开始导入数据之前,临时禁用表中的索引和约束。这可以显著提高数据导入速度。
-- 禁用索引 (MySQL, 示例)
ALTER TABLE news_table DISABLE KEYS;
-- 禁用外键约束
SET foreign_key_checks = 0;
2. 分批导入数据
将数据分成较小的批次进行导入。批次大小可以根据数据库性能进行调整,通常每批几千到几万行。
-- 示例:使用LOAD DATA INFILE导入数据 (MySQL, 示例)
LOAD DATA INFILE 'path/to/datafile.csv'
INTO TABLE news_table
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(column1, column2, ..., column15);
3. 恢复索引和约束
一旦数据导入完成,重新启用索引和约束,并重建索引。
-- 启用索引 (MySQL, 示例)
ALTER TABLE news_table ENABLE KEYS;
-- 启用外键约束
SET foreign_key_checks = 1;
4. 优化数据库配置
在导入数据之前,可以调整一些数据库配置参数以优化性能。例如:
-- 增大InnoDB缓冲池大小 (MySQL, 示例)
SET GLOBAL innodb_buffer_pool_size = 2 * 1024 * 1024 * 1024;
-- 2GB
-- 增大事务日志缓冲区大小
SET GLOBAL innodb_log_buffer_size = 256 * 1024 * 1024; -- 256MB
额外注意事项
- 事务控制:确保每批导入的数据在一个事务中进行,以确保数据一致性。
- 备份和恢复:在进行大规模数据导入操作之前,务必进行数据备份。
- 日志管理 :大规模导入数据可能会生成大量日志,确保有足够的磁盘空间。
通过以上步骤,可以显著提高大规模数据导入的速度,同时确保数据的完整性和一致性。
阅读材料
为了进一步了解 InnoDB引擎与MyISAM引擎中索引的区别,可以阅读一下如下地址中的文章
引擎详解