从入门到精通【MySQL】 JDBC

发布于:2025-04-18 ⋅ 阅读:(25) ⋅ 点赞:(0)

📕1. 什么是JDBC

JDBC(Java Data Base Connectivity, Java数据库连接)是Java程序和数据库之间的桥梁,包含了一套Java定义的用于执行SQL语句的接口,使开发者能够编写数据库的程序。JDBC 的主要作用是:与数据库建立连接、发送SQL语句和处理数据库执行结果。

📕2. JDBC的使用原理

首先回顾一下我们使用Navicat客户端操作MySQL数据库的过程:
a. 连接到数据库
b. 发送SQL语句
c. 执行SQL语句
d. 显示得到的结果
e. 关闭连接

同样如果使用程序操作数据库也会经历以上几步,但是不同的数据库对于同一个操作不论是协议还是参数都各有不同,如果让程序员自己去实现,那就必须针对不同的数据库进行编码实现,这个工作量和维护成本显然太大。Java采取的做法是把以上操作步骤定义了相应的接口,具体的实现交给数据库厂商去做,Java程序员只需要按照需要调用接口中定义的方法即可,这样不论使用什么数据库,都对于Java程序没有任何影响,即便是换一个数据库,也只需要换一下相应厂商的实现依赖。

JDBC工作原理简洁地概括为:

1. 加载数据库厂商的驱动包(告诉程序该使用哪一个数据库)
2. 建立连接
3. 创建Statement对象(用来执行SQL语句的对象)
4. 执行SQL
5. 处理返回结果
6. 释放资源和关闭连接

📕3. 使用JDBC具体步骤

✏️3.1 标题获取MySQL驱动包并修改pom.xml文件

在Maven仓库搜索MySQL,找到最新版的驱动包(点击即可)

修改pom.xml文件:在Maven工程中的pom.xml文件中的 标签中添加MySQL依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>
✏️3.2 建立数据库连接

首先给大家介绍一下URL,在数据库连接中,URL(Uniform Resource Locator,统一资源定位符)参数起着关键作用。以下是对数据库 URL 参数的解释说明:

一. 通用结构

jdbc:mysql://[host][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...

二. 各部分含义

  1. jdbc:mysql://
这是 JDBC 连接 MySQL 数据库的前缀标识,表明使用 JDBC 连接 MySQL 数据库驱动程序。
  1. [host]
数据库服务器的主机名或 IP 地址。指定数据库服务器所在的位置,例如 “localhost” 表示本地主机,或者是一个具体的 IP 地址如“192.168.1.100”。
  1. [:port]
数据库服务器的端口号。MySQL 的默认端口号是 3306,但如果数据库服务器配置为使用不同的端口,则需要在 URL中指定正确的端口号。
  1. [database]
要连接的数据库名称。指定要连接和操作的具体数据库。
  1. [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]…
常用连接参数:


allowPublicKeyRetrieval=true|false:
含义:决定是否允许客户端从服务器自动检索公钥。如果设置为true,则允许检索公钥,这在某些情况下可以解决连接问题,但可能会带来一定的安全风险。如果设置为false,则不允许检索公钥。


useSSL=true|false:
含义:指定是否使用 SSL(Secure Sockets Layer)加密连接。设置为true表示使用 SSL
加密连接,确保数据在传输过程中的安全性;设置为false表示不使用 SSL 连接。


characterEncoding=[encoding]:
含义:设置连接的字符编码。常见的编码有UTF-8、GBK等。确保客户端和服务器之间的数据传输使用正确的字符编码,以避免出现乱码问题。


autoReconnect=true|false:
含义:当连接断开时,决定是否自动重新连接。如果设置为true,在连接断开时,驱动程序会尝试自动重新连接到数据库;如果设置为false,则不会自动重新连接。


zeroDateTimeBehavior=[behavior]:
含义:指定当数据库返回零日期时间值时的处理方式。常见的行为有exception(抛出异常)、convertToNull(转换为null)等。


不常用连接的参数:


serverTimezone=[timezone]:
含义:设置服务器的时区。确保数据库中的日期时间值与客户端的时区一致,避免出现时间不一致的问题。


connectTimeout=[milliseconds]:
含义:指定连接超时时间,以毫秒为单位。如果在指定的时间内无法建立连接,则连接尝试将失败。


socketTimeout=[milliseconds]:
含义:设置套接字超时时间,以毫秒为单位。指定在读取或写入数据库时等待的最长时间,如果超过这个时间仍未完成操作,则会抛出超时异常。

• 使用驱动管理类 DriverManager 的静态发法获取数据库连接

在这里插入图片描述

• 通过数据源 DataSource 对象获取(更推荐使用这种方式建立数据库连接)
在这里插入图片描述

✏️3.3 创建Statement

Statement是用 于执行静态SQL语句并返回执行结果的对象
在这里插入图片描述

✏️3.4 执行SQL语句

• 执行select查询时返回的是⼀个结果集,用ResultSet接收
• 执行nsert, update, delete操作时,返回的是受影响的行数,用int类型接收
在这里插入图片描述
执行前:
在这里插入图片描述

✏️3.5 处理返回结果

在这里插入图片描述
执行后:
在这里插入图片描述

✏️3.6 释放资源和关闭连接

在这里插入图片描述

📕4. JDBC中常用的类和接口

✏️4.1 DriverManager 和DataSource
  • DriverManager类是JDBC的管理层,用来管理数据库中的驱动程序,在使用java操作数据库之前,必须使用class类的静态方法forName(String classname)加载能够连接数据库的驱动程序。
  • DataSource数据源是DriverManager的替代方案,始于JDK1.4,是获取数据库连接的首选方法

DriverManager 与 DataSource 的区别

  • DriverManager每次调用getConnection方法都会初始化⼀个新的连接,使用完成后会关闭真实连接,导致资源浪费
  • DataSource使用了连接池的技术,会在初始化时创建⼀定数量的数据库连接,这些连接可以重复使用,关闭时并不是真正关闭连接,而是将连接归还给连接池,以供后续使用,有效地提高资源利用率和和性能(池化技术后续进阶篇会介绍)
✏️4.2 Connection 数据库连接

Connection接口代表java端与指定数据库之间的连接,Connection接口的常用方法及说明如下表:

方法 功能描述
createStatement() 创建Statement对象
createStatement(int resultSetType,int resultSetConcurrency) 创建Statement对象,Statement对象被用来生成一个具有给定类型、并发性和可保存性的ResultSet对象
prepareStatement() 创建预处理prepareStatement对象
prepareCall(String sql) 创建一个CallableStatement对象来调用数据库存储过程
isReadOnly() 查看当前Connection对象的读写模式是否是只读模式
setReadOnly() 查看当前Connection对象的读写模式,默认为非只读模式
commit() 事上一次提交/回滚后进行的更改成为持久更改,并释放此Connection对象当前持有的数据库锁
roolback() 取消在当前事务中进行的更改,并释放此Connection对象当前持有的数据库锁
close() 立即释放此Connection对象的数据库和JDBC资源,而不是等待它们被自动释放
✏️4.3 Statement 对象
🔖4.3.1 Statement

用于执行静态SQL语句并返回执行结果

方法 功能描述
execute(String sql) 执行静态的SELECT语句,该语句可能返回多个结果集
executeQuery(String sql) 执行给定的SQL语句,该语句返回单个ResultSet对象
clearBatch() 清空此Statement对象的当前SQL命令列表
executeBatch() 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组,数组元素的排序与SQL语句的添加顺序对应
addBatch() 将给定的SQL命令添加到此Statement对象的当前命令列表中,如果驱动程序不支持批量处理,将抛出异常
close() 释放Statement对象占用的数据库和JDBC资源
executeUpdate() 执行前面包含的参数的动态INSERT、UPDATE或DELETE语句

由于只能执行静态语句,所以这里会有⼀个问题,假设一个语句中需要动态的参数,比如where子句中的条件,那么只能通过字符串拼接的方式组装完成的SQL语句,比如:

String sql = "select * from student where name = '" + name + "' and class_id = " + classId;

字符串拼接形式构造SQL语句时,如果不处理参数中的特殊字符就会造成SQL注入,这是一个非常
严重的安全性问题。

🔖4.3.2 SQL注入

SQL注入即是指web应用程序对用户输⼊数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进⼀步得到相应的数据信息。

示例:
• 姓名条件宋江和班级编号条件 1 是动态的参数

# 正常的查询,没有符合的结果
mysql> select * from student where name = '宋江' and class_id = 1;
Empty set (0.01 sec)

• 构造恶意参数来执行非法的SQL,把正常的条件值宋江替换为 ’ or 1 = 1;–

# 查询出来了所有的记录,此时学⽣表中的数据全部都将泄漏
mysql> select * from student where name = '' or 1 = 1;-- 宋江' and class_id = 1;
+----+----------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+----------+--------+------+--------+-------------+----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 |
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 2 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 2 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 2 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 2 |
+----+----------+--------+------+--------+-------------+----------+
8 rows in set (0.01 sec)
🔖4.3.3 PreparedStatement

预编译SQL语句对象,SQL语句被预编译并存储在PreparedStatement对象中,可以使用该对象多次
执行SQL语句,同时可以解决SQL注入问题。

示例:通过Connection对象获取到PreparedStatement对象,需要传入SQL模板,动态参数用占位
符 ? 表示。

// 获取了个处理SQL的PrepareStatement对象
PreparedStatement preparedStatement = connection.prepareStatement("select id, 
name, sno, age, gender, enroll_date, class_id from student where name = ? and 
class_id = ?");
// ⽤真实值去替换占位符
preparedStatement.setString(1, "宋江");
preparedStatement.setLong(2, 2);
📕4.4 ResultSet结果集

ResultSet接口类似于一个临时表,用来暂时存放对数据库中的数据执行查询操作后的结果,ResultSet对象具有指向当前数据行的指针,指针开始的位置在第一条记录上,通过next()方法可向下移动指针,ResultSet接口的常用方法以及说明如下表:
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到