当前位置: 首页 > news >正文

MySQL终章(8)JDBC


目录

1.前言

2.正文

2.1JDBC概念

2.2三种编码方式

2.2.1第一种

2.2.2第二种(优化版)

2.2.3第三种(更优化版)

3.小结


1.前言

哈喽大家好吖,今天来给大家带来Java中的JDBC的讲解,之前学习的都是操作数据库的sql语言,那么我们如何通过程序来操作数据库呢?就是通过JDBC了,正文开始。

2.正文

2.1JDBC概念

JDBC是干什么的呢?

目的:使Java程序能够通过统一接口访问多种关系型数据库(如MySQL、Oracle、PostgreSQL等)。
核心思想:通过驱动(Driver)实现与具体数据库的解耦,开发者只需调用JDBC API,无需关心底层数据库差异。

访问数据库的常用流程:

  1. 确定数据库服务器的地址,端口号。(数据源)
  2. 建立连接,用户名,密码。(不同的数据库以哪种协议建立连接)(数据库连接)
  3. 发送要执行的SQL。(以什么样的形式发送,这里主要考虑编码的格式,即协议)(执行对象)
  4. 接收返回结果 (结果集,受影响的行数)  以哪种协议解析结果。 (结果集)
  5. 关闭连接。(释放资源,关闭连接)

JDBC是JAVA平台提供的接口,具体的实现是由数据库厂商去完成的。

2.2三种编码方式

在JDBC前记得先在maven中导入jar包:

Maven Repository: Search/Browse/Explorehttps://mvnrepository.com/pom文件是这样:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>

测试的数据库代码我也在这里先提供给大家:

create database StudyRoom;
use StudyRoom;
-- 用户表
CREATE TABLE users (user_id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) UNIQUE NOT NULL,password VARCHAR(255) NOT NULL,phone VARCHAR(20) UNIQUE NOT NULL,email VARCHAR(100),school VARCHAR(100),points INT DEFAULT 0
);INSERT INTO users values(01,'tom','12345','123456789','@123456789','HEDU',10)

正式开始: 

2.2.1第一种

代码:

import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;public class jdbc1 {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// 1. 加载数据库厂商提供的驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2. 获取数据库连接connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/studyroom?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");// 3. 创建Statement对象statement = connection.createStatement();// 4. 定义SQL并执行SQL语句System.out.println("请输入学生编号:");Scanner scanner = new Scanner(System.in);// 接收用户的输入int id = scanner.nextInt();String sql = "select user_id, username, password, phone, email, school, points from users where user_id = '" + id + "'";// 5. 执行SQL,获取查询结果resultSet = statement.executeQuery(sql);// 6. 对结果集进行遍历,获取数据// 如果一下条有记录,返回true,没有则返回falsewhile (resultSet.next()) {// 获取学生Idlong user_id = resultSet.getLong(1);String username = resultSet.getString(2);String password = resultSet.getString(3);String phone = resultSet.getString(4);String email = resultSet.getString(5);String school = resultSet.getString(6);long points= resultSet.getLong(7);System.out.println(MessageFormat.format("学生编号={0}, 姓名={1}, 密码={2}, 手机号={3}, 邮箱={4}, 学校={5}, 点数={6}", user_id, username, password, phone, email, school, points));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {// 依次释放资源,关闭连接if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}

核心思路讲解:

1.加载数据库驱动

  • 使用 Class.forName("com.mysql.cj.jdbc.Driver") 加载 MySQL 数据库的 JDBC 驱动类,这是建立与 MySQL 数据库连接的必要步骤,让 Java 程序能够识别并使用 MySQL 的驱动来与数据库进行通信。

2.获取数据库连接

  • 通过 DriverManager.getConnection 方法,使用数据库的 URL(包括数据库的地址、端口、数据库名以及一些连接参数,如字符编码、是否允许公钥检索、是否使用 SSL 等)、用户名和密码来获取与数据库的连接,将返回的连接赋值给 connection 对象。

3.创建 Statement 对象

  • 调用 connection 对象的 createStatement 方法创建一个 Statement 对象,这个对象用于向数据库发送 SQL 语句并执行。

4.定义 SQL 查询语句并执行

  • 提示用户输入学生编号,并通过 Scanner 对象接收用户的输入。

  • 根据用户输入的学生编号构建 SQL 查询语句,查询 users 表中对应学生编号的相关信息,包括 user_id、username、password、phone、email、school、points 等字段。

  • 使用 statement 对象的 executeQuery 方法执行构建好的 SQL 查询语句,将查询结果存储在 resultSet 对象中。

5.处理查询结果

  • 使用 while 循环和 resultSet 对象的 next 方法遍历查询结果集,每次调用 next 方法都会将结果集中的指针向下移动一行,如果还有数据则返回 true,否则返回 false。

  • 在循环体内,使用 resultSet 对象的 get 系列方法(如 getLonggetString 等)根据字段的顺序或列名获取每一行数据中的各个字段值。

  • 使用 MessageFormat.format 方法将获取到的字段值按照指定的格式(包含占位符)组合成一个字符串,并输出到控制台,显示学生的所有相关信息。

6.关闭资源

  • 在 finally 块中,依次判断 resultSet、statement、connection 对象是否不为 null,如果不为 null,则分别调用它们的 close 方法关闭这些资源,释放数据库连接和相关资源,这是非常重要的一步,避免了资源泄漏的问题。即使在执行过程中出现异常,finally 块中的代码也会被执行,确保资源被正确关闭。

2.2.2第二种(优化版)

代码:

import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.*;
import java.text.MessageFormat;
import java.util.Scanner;public class jdbc2 {public static void main(String[] args) {// 定义MySQL数据源对象MysqlDataSource mysqlDataSource = new MysqlDataSource();// 设置数据库连接串mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/studyroom?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false");// 用户名mysqlDataSource.setUser("root");// 密码mysqlDataSource.setPassword("123456");// 定义JDBC的数据源对象DataSource dataSource = mysqlDataSource;// 定义连接对象Connection connection = null;// 定义预处理SQL执行对象PreparedStatement statement = null;// 定义结果集对象ResultSet resultSet = null;try {// 1. 通过数据源获取数据库连接connection = dataSource.getConnection();// 2. 获取预处理SQL执行对象//输入System.out.println("请输入学生编号:");Scanner scanner = new Scanner(System.in);int id = scanner.nextInt();// 定义要执行的SQLString sql = "select user_id, username, password, phone, email, school, points from users where user_id = ?";statement = connection.prepareStatement(sql);// 3. 用真实值替换占位符statement.setInt(1, id);// 4. 执行SQL,获取结果集resultSet = statement.executeQuery();// 5. 遍历结果集while (resultSet.next()) {// 获取学生Idlong user_id = resultSet.getLong(1);String username = resultSet.getString(2);String password = resultSet.getString(3);String phone = resultSet.getString(4);String email = resultSet.getString(5);String school = resultSet.getString(6);long points= resultSet.getLong(7);System.out.println(MessageFormat.format("学生编号={0}, 姓名={1}, 密码={2}, 手机号={3}, 邮箱={4}, 学校={5}, 点数={6}", user_id, username, password, phone, email, school, points));}} catch (SQLException e) {e.printStackTrace();} finally {// 依次释放资源,关闭连接if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}

核心思路讲解:

1.配置数据库连接信息

  • 创建 MysqlDataSource 对象,通过设置其 URL、用户名和密码来配置数据库连接信息,这种方式将连接信息集中管理,使得代码更加清晰和易于维护,方便后续对连接信息的修改。

2.获取数据库连接

  • 将配置好的 MysqlDataSource 对象赋值给 DataSource 类型的变量 dataSource,然后通过 dataSource 的 getConnection 方法获取数据库连接,这与直接使用 DriverManager 获取连接相比,更符合 JDBC 的最佳实践,便于后续进行连接池等高级功能的集成。

3.使用 PreparedStatement 执行 SQL 语句

  • 定义 SQL 语句时使用了占位符 "?",然后通过 connection.prepareStatement(sql) 获取 PreparedStatement 对象,这种方式可以有效防止 SQL 注入攻击,因为 PreparedStatement 会对参数进行预编译和转义处理。

  • 使用 statement.setInt(1, id) 将用户输入的学生编号设置到 SQL 语句的占位符位置,将参数与 SQL 语句分离,提高了代码的安全性和可读性。

4.执行查询和处理结果

  • 调用 statement.executeQuery() 执行查询操作,获取结果集。

  • 遍历结果集的方式与之前的代码类似,通过 resultSet.next() 移动指针并获取数据,然后使用 MessageFormat.format 方法输出格式化后的学生信息。

5.关闭资源

  • 在 finally 块中关闭资源的逻辑与之前代码相同,确保无论是否出现异常,都会关闭 resultSet、statement 和 connection 对象,释放数据库资源。


相比第一种有哪些优化呢?

  • 数据库连接管理 :之前的代码直接通过 DriverManager.getConnection 获取连接,而本代码使用了 MysqlDataSource 数据源来配置和获取连接,这种方式更灵活,便于后续进行连接池等优化,提高了代码的可维护性和可扩展性。

  • SQL 注入防护 :之前的代码通过字符串拼接构建 SQL 语句,容易受到 SQL 注入攻击,而本代码使用了 PreparedStatement 和参数占位符的方式,有效防止了 SQL 注入问题,增强了程序的安全性。

  • 代码可读性和可维护性 :通过将数据库连接信息集中配置在数据源中,以及使用 PreparedStatement 的参数设置方式,使得代码结构更加清晰,便于理解和后续的维护。

2.2.3第三种(更优化版)

我们发现,如果每一次尝试通过程序来操作数据库都要一次一次建立连接,代码会非常麻烦,于是我们引入连接池的概念,将连接数据库与释放资源的操作封装起来,这样就会非常方便。

代码结构:

DButil:

package utils;import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class DButil {private static DataSource dataSource = null;private static final String URL = "jdbc:mysql://127.0.0.1:3306/studyroom?characterEncoding=utf8" +"&allowPublicKeyRetrieval=true&useSSL=false";private static final String USER = "root";private static final String PASSWORD = "123456";static {MysqlDataSource mysqlDataSource = new MysqlDataSource();mysqlDataSource.setURL(URL);mysqlDataSource.setUser(USER);mysqlDataSource.setPassword(PASSWORD);dataSource = mysqlDataSource;}private DButil(){}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}public static void close(ResultSet resultSet, Statement statement,Connection connection){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection != null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}

JDBC3:

package com.example.demo;import utils.DButil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Scanner;public class jdbc3 {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;try {connection = DButil.getConnection();String sql = "select user_id, username, password, phone, email, school, points from users where user_id = ?";statement = connection.prepareStatement(sql);Scanner scanner = new Scanner(System.in);int id = scanner.nextInt();statement.setInt(1,id);ResultSet resultSet = statement.executeQuery();while (resultSet.next()) {// 获取学生Idlong user_id = resultSet.getLong(1);String username = resultSet.getString(2);String password = resultSet.getString(3);String phone = resultSet.getString(4);String email = resultSet.getString(5);String school = resultSet.getString(6);long points= resultSet.getLong(7);System.out.println(MessageFormat.format("学生编号={0}, 姓名={1}, 密码={2}, 手机号={3}, 邮箱={4}, 学校={5}, 点数={6}", user_id, username, password, phone, email, school, points));}} catch (SQLException e) {e.printStackTrace();} finally {DButil.close(null,statement,connection);}}
}

代码核心思路:

DButil 类(工具类)

  • 功能

    • 专门用于管理数据库连接和资源关闭的工具类,将数据库连接的获取和资源关闭的逻辑抽取出来,方便在多个地方复用,避免重复代码,提高代码的可维护性和复用性。

  • 静态代码块初始化数据源

    • 在类加载时,通过静态代码块创建并配置 MysqlDataSource 对象,设置数据库的 URL、用户名和密码,并将其赋值给 dataSource 对象。这种方式确保数据源只初始化一次,提高了效率。

  • 私有构造方法

    • 将构造方法私有化,防止外部创建该工具类的实例,因为工具类主要用于提供静态方法,不需要实例化。

  • 获取数据库连接

    • 提供 getConnection 静态方法,通过调用 dataSource.getConnection() 向外提供数据库连接对象,方便其他类使用。

  • 关闭资源

    • 提供 close 静态方法,接收 ResultSetStatementConnection 对象作为参数,并依次判断它们是否不为 null,若不为 null 则关闭它们,释放资源。这样统一管理资源关闭逻辑,避免资源泄漏。


jdbc3 类(主程序类):

  • 功能

    • 使用 DButil 工具类获取数据库连接,并通过 PreparedStatement 执行 SQL 查询语句,根据用户输入的学生编号查询学生信息并输出。

  • 获取数据库连接

    • 调用 DButil.getConnection() 方法获取数据库连接,而不是像之前的代码直接在主程序中配置连接信息和创建连接,这样使得数据库连接的获取更加规范和集中管理。

  • 执行 SQL 查询

    • 定义 SQL 语句时继续使用占位符 "?",并通过 connection.prepareStatement(sql) 获取 PreparedStatement 对象,然后使用 statement.setInt(1, id) 设置参数值,有效防止 SQL 注入,同时提高代码的可读性和安全性。

  • 处理查询结果和关闭资源

    • 执行查询获取结果集后,遍历结果集并输出学生信息,这部分逻辑与之前的代码类似。

    • 在 finally 块中调用 DButil.close 方法关闭资源,而不是像之前在主程序中手动关闭,简化了资源关闭的代码,减少了出错的可能性。


优化点:

  • 代码复用和单一职责 :将数据库连接的获取和资源关闭的逻辑抽取到专门的 DButil 工具类中,遵循单一职责原则,使每个类的职责更加明确,提高了代码的复用性。在之前的代码中,这些逻辑都分散在主程序中,导致代码重复且不易维护。

  • 资源管理更规范 :通过工具类统一管理资源关闭,确保在任何情况下(即使出现异常)都能正确关闭资源,避免资源泄漏的问题。之前的代码虽然也有在 finally 块中关闭资源,但随着项目规模的扩大和复杂性的增加,这种方式容易出现遗漏或错误。

  • 提高可维护性和可扩展性 :如果将来需要更改数据库连接信息或切换数据库类型,只需修改 DButil 类中的相关配置即可,而无需修改每个使用数据库连接的地方,大大提高了代码的可维护性和可扩展性。

运行截图:

 

3.小结

今天的分享到这里就结束了,喜欢的小伙伴点点赞点点关注,你的支持就是对我最大的鼓励,大家加油!

http://www.xdnf.cn/news/88885.html

相关文章:

  • OpenCV --- 图像预处理(六)
  • 小白工具视频转MPG, 功能丰富齐全,无需下载软件,在线使用,超实用
  • 基于Spring Security 6的OAuth2 系列之二十六 - 终章
  • 2537. 统计好子数组的数目
  • AI深度伪造视频用于诈骗的法律定性与风险防范
  • 【Vue】路由管理(Vue Router)
  • Java ByteBuf解析和进制转换汇总
  • Spark-SQL 项目
  • Linux安装后无法启动24天
  • 数据集 | 柑橘果目标检测数据集
  • 大数据开发的基本流程
  • 基于机器学习的房租影响因素分析系统
  • 安卓模拟器绕过检测全解析:雷电、MuMu、蓝叠、逍遥、夜神与WSA完整指南
  • 3.1.1 MaterialDesign中DrawerHost使用案例
  • Kubernetes Docker 部署达梦8数据库
  • 蓝桥杯算法实战分享:C/C++ 题型解析与实战技巧
  • 明远智睿2351开发板:四核1.4G处理器——开启高效能Linux系统新纪元
  • 『不废话』之Python管理工具uv快速入门
  • 【Java】Hibernate的检索策略
  • python的深拷贝浅拷贝(copy /deepcopy )
  • 三维几何变换
  • usb2.0的硬件知识(一)
  • 查看MySql操作日志
  • 布隆过滤器的应用
  • 《Operating System Concepts》阅读笔记:p764-p766
  • 【Axure视频教程】不透明度函数
  • 以下是一个基于 ESP32 - S3 实现消息队列收发测试的 C 例程
  • crontab 定时备份 mysql 数据库
  • CF思维题(cf round 1019 div.2 b题)
  • ADS基本操作之S参数仿真