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

1、JDBC的应用场景
如果JAVA要访问不同的数据库,那么就需要根据数据库的协议进行代码的开发, 为了解决不同数据的使用场景,JAVA中只定义了用于连接和操作数据的接口--JDBC具体的实现由数据库厂商来完成
2、JDBC工作原理
JDBC工作原理简洁地概括为:加载驱动、建立连接、创建Statement、执行SQL、处理结果和关闭资源。
2.为什么要使用JDBC
• 首先回顾⼀下使用客户端操作数据库的过程,主要分为以下几步:
- 数据源:确认数据库的服务器的地址和端口号
- 数据库连接:连接到数据库服务,不同的数据库以哪种协议建立连接
- 执行对象:发送SQL语句,以什么样的形式发送,这里注意考虑编码的格式(协议)
- 结果集:接受返回结果并显示(结果集,受影响行数) 以哪种协议解析的结果
- 释放资源关闭连接:关闭连接
对于JAVA程序员来说,肯定要处理不同数据库之间对数据的编解码,但只需要调用JDBC定义的方法就可完成数据库的具体操作:
• 同样如果使用程序操作数据库也会经历以上几步,⼤家应该可以想到,为实现上述步骤,可以编写相应的代码实现数据库连接,发送SQL语句,处理结果并显示,最后关闭连接。
• 但是不同的数据库对于同⼀个操作不论是协议还是参数都各有不同,如果让程序员自己去实现,那就必须针对不同的数据库进行编码实现,这个工作量和维护成本显然太大。
• Java采取的做法是把以上操作步骤定义了相应的接口,具体的实现交给数据库厂商去做,Java程序员只需要按照需要调用接口中定义的方法即可,这样不论使用什么数据库,都对于Java程序没有任何影响,即便是换⼀个数据库,也只需要换⼀下相应厂商的实现依赖。
简单来说,JDBC 是Java平台的一个接口,通过这五步骤,脱离数据库操作数据库,数据库厂商提供了具体的实现类,下面就是一些不同的实现
Java的就是第三个,Connector/J

• JDBC使用过程可以概括为:加载数据库厂商的驱动包、建立连接、创建Statement、执行SQL、 处理结果释放资源和关闭连接。
3.使用JDBC
1.在设置里检查自己的maven 是idea 内置的maven还是镜像的
maven 类似与应用商店,Java把用到的依赖放到maven 这个'应用商店'里,maven 维护了Java工程需要用的依赖,这个默认仓库是国外的,需要把他修改成国内的。
1.修改maven 的配置,找到idea 的安装路径

点击进去plugins ,里面找到maven

点击进去,再点击meavn3,到达这个路径

点击 conf ,找到settings.xml,这个就是我们修改的配置文件

打开,找到mirror 这个节点

把这个替换了,修改之前最好就是备份一下要不然就用不了了
java
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>central</id>
<mirrorOf>*</mirrorOf>
<name>aliyun central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
<id>spring</id>
<mirrorOf>*</mirrorOf>
<name>aliyun spring</name>
<url>https://maven.aliyun.com/repository/spring</url>
</mirror>
<!-- 加入如下mirror节点 使用国内阿里云仓库镜像 结束-->
</mirrors>
创建idea项目,然后双击点击src ,创建一个新的模块

advanced setting :
这是 Maven 项目中的坐标配置项,用于唯一标识项目或依赖:
- GroupId :组织 / 公司的唯一标识,通常是域名倒写(如
org.example),用来区分不同组织的项目。 - ArtifactId:项目或模块的具体名称,在同一个 GroupId 下唯一,代表项目本身或其中的某个模块。
2.创建一个maven 工程

3 获取MySQL驱动包(jar)
• 在Maven仓库https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.33搜索MySQL,找到最新版的驱动包

在Maven仓库mvnrepository.com搜索MySQL,找到最新版的驱动包
第一个是最新的jar包,第二个是历史版本的jar包 ,去找我们的版本

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
4.修改pom.xml文件
在pom.xml文件,在<dependencies>节点中安装依赖
<!--管理依赖的节点 -->
<dependencies>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<!-- JDBC 的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
完事后点击右上角的刷新

如果说这里的出现了8.0.33也就是刚才在pom.xml 中添加的依赖,也说明已经加载到工程中了
5. 建立数据库连接
1.• 使用驱动管理类 DriverManager 的静态方法获取数据库连接
java
// 加载数据库厂商提供的驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取数据库连接
Connection connection =
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jobs_info_db?characterEncoding" +
"=utf8&allowPublicKeyRetrieval=true&useSSL=false",
"root",
"123456");
1.注册数据库厂家提供的驱动,通过完全限定名加载指定的类到JVM下,如下

- Surround with try/catch:用 try/catch 包围

这是点击forName的使用规范
2.数据库的连接
1.导入 代码片段,复制URL
java
connection = java.sql.DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8" +
"&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
jdbc:mysql://:固定协议前缀,标识这是 MySQL 数据库的 JDBC 连接。127.0.0.1:数据库服务器的 IP 地址,127.0.0.1表示本地服务器(也可写localhost)。3306:MySQL 数据库的默认端口号,若未修改过数据库端口,保持此值即可。java01:要连接的具体数据库名称,需提前在 MySQL 中创建该数据库。?后的参数:连接的附加配置,用于解决编码、安全等问题characterEncoding=utf8:指定字符编码为 UTF-8,避免中文数据存储或查询时出现乱码。allowPublicKeyRetrieval=true:允许客户端从服务器获取公钥(MySQL 8.0+ 版本连接时的常见配置,解决公钥检索相关的连接问题)。useSSL=false:关闭 SSL 加密连接(开发环境常用,生产环境可根据安全需求开启)。

注意:这里DriverManager 应该是Java.sql 的

还报错,这里还要在抛一个异常,就不会报错了

2.在补上输入账号和密码
3.创建Statement对象,用来执行sql 的语句
java
// 通过connection获取statement对象
Statement statement = connection.createStatement();

4.定义并执行sql语句
java
String sql = "select student_id, sn, name, mail, class_id from student where name = '" + name + "'";
但是name 我们没有定义,我们就要自己输入读取完再查找,这个名字的信息(sql 的;可加可不加)
java
System.out.println("请输入学生姓名:");
Scanner scanner = new Scanner(System.in);
// 接收用户的输入
String name = scanner.next();
String sql = "select student_id, sn, name, mail, class_id from student where name = '" + name + "'";
5.执行语句
java
// 5. 执行SQL,获取查询结果
statement.executeQuery(sql);
//执行语句
statement.executeUpdate(sql);
//执行insert, delete , update语句
-
sstatement.executeQuery(sql);专门用于执行 查询语句(如SELECT) ,执行后会返回一个ResultSet对象,用于封装查询结果集(可以通过遍历ResultSet来获取每一条数据) -
statement.executeUpdate(sql);专门用于执行数据操作语句(DML) 或数据定义语句(DDL):- 执行 DML(增删改)时,返回受影响的行数(如插入 3 条数据返回 3)。
- 执行 DDL(如创建表、删除表)时,返回 0(因为 DDL 不涉及行数影响)
实际开发中:
executeQuery()(专门执行查询,直接返回 ResultSet)
executeUpdate()(专门执行增删改 / DDL)
6.获取查询结果
java
ResultSet resultSet = statement.executeQuery(sql);
7.对结果集进行遍历
java
while (resultSet.next()) {
}
java
while (resultSet.next()) {
// 获取学生Id
long stuId = resultSet.getLong(1);
//bigint 就是long 都是8字节
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
long classId = resultSet.getLong(5);
System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 学生姓名={2}, 邮箱={3}, 班级编号={4}", stuId, stuSn,stuName, stuMail, classId));
}
5.关闭连接
因为作用域的原因,我们把前面的resultSet Connection和Statement 都从try提出来
预编译语句(如 PreparedStatement)是防止 SQL 注入的重要手段,它能将 SQL 语句的结构和数据分开处理,避免恶意输入被解析为 SQL 命令执行。而未使用预编译时,攻击者可能通过构造特殊输入(如你提到的去除空格、插入注释符等)来篡改 SQL 语句的逻辑,从而非法获取、修改或删除数据库信息。
每次获取的都是getConnection 都是一次物理连接,也就是每次执行语句都会打开这个界面,但是我们正常的登录mysql 是打开一次命令行,然后执行语句 DataSource一次连接可以执行多次,直到这个连接被关闭,也就是关闭这个数据源

2.• 通过数据源 DataSource 对象获取,推荐在实际开发中应用这种方式
一个连接可以执行多次SQL,直到关闭数据源
通过一个连接池去管理很多个连接,当需要SQL执行的时候,从连接池里拿一个空间连接出来,用完后返还给连接池。
java
//设置数据源的连接串、⽤⼾名和密码
MysqlDataSource mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/jobs_info_db?
characterEncoding" +
"=utf8&allowPublicKeyRetrieval=true&useSSL=false");
mysqlDataSource.setUser("root");
mysqlDataSource.setPassword("123456");
// 把mysqlDataSource 转换为JDBC的dataSource DataSource dataSource = mysqlDataSource;
MySQL数据库连接URL格式: jdbc:mysql:// 服务器地址 : 端口 / 数据库 ? 参数名 = 值 [& 参数名 = 值...]
数据源(DataSource) 是一个抽象概念,本质上是管理数据库连接的 "中间件" 或 "接口",它封装了数据库的连接信息
与第一种有一点不一样但是思路是一样的
1.创建一个数据源对象
java
/ 定义MySQL数据源对象
MysqlDataSource mysqlDataSource = new MysqlDataSource();
// 设置数据库连接
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8&allowPublicKeyRetrieval" +
"=true&useSSL=false");
2.设置URl,root,密码
java
// 设置数据库连接串
mysqlDataSource.setURL("jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8&allowPublicKeyRetrieval" +
"=true&useSSL=false");
// 用户名
mysqlDataSource.setUser("root");
// 密码
mysqlDataSource.setPassword("123456");
// 定义JDBC的数据源对象
DataSource dataSource = mysqlDataSource;
3.定义JDBC 的数据源对象
sql
// 定义JDBC的数据源对象
DataSource dataSource = mysqlDataSource;
4.跟第一种方法一样,把他们提出来
java
// 定义连接对象
Connection connection = null;
// 定义预处理SQL执行对象
PreparedStatement statement = null;
// 定义结果集对象
ResultSet resultSet = null;
5.通过数据源获取数据库连接
java
// 1. 通过数据源获取数据库连接
connection = dataSource.getConnection();
6.获取预处理SQL执行对象
java
// 2. 获取预处理SQL执行对象
// 定义要执行的SQL
String sql = "select student_id, sn, name, mail, class_id from student where name = ?";
statement = connection.prepareStatement(sql);
7.接收用户的输入,并将前面用占位符的name 的内容获取
java
// 接收用户的输入
System.out.println("请输入学生姓名:");
Scanner scanner = new Scanner(System.in);
String name = scanner.next();
// 3. 用真实值替换占位符
statement.setString(1, name);
8.获取结果集
java
// 4. 执行SQL,获取结果集
resultSet = statement.executeQuery();
9.循环遍历
java
while (resultSet.next()) {
// 获取学生Id
long stuId = resultSet.getLong("student_id");
String stuSn = resultSet.getString(2);
String stuName = resultSet.getString(3);
String stuMail = resultSet.getString(4);
long classId = resultSet.getLong(5);
System.out.println(MessageFormat.format("学生编号={0}, 学号={1}, 学生姓名={2}, 邮箱={3}, 班级编号={4}", stuId, stuSn,
stuName, stuMail, classId));
}
10.释放资源跟第一种方法一样
java
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();
}
}
}
}
3.优化第二种
1.设置成静态的无法改变的成员变量
java
// 数据源
private static DataSource dataSource = null;
// 数据库连接串
private static final String URL = "jdbc:mysql://127.0.0.1:3306/java113?characterEncoding=utf8" +
"&allowPublicKeyRetrieval=true&useSSL=false";
// 用户名
private static final String USER = "root";
// 密码
private static final String PASSWORD = "123456";
- 通过静态代码块初始化数据源:在类加载时就完成
MysqlDataSource的配置(设置 URL、用户名、密码),并赋值给dataSource变量,确保全局只有一个数据源实例,避免重复初始化。
2.执行数据源的初始化
java
// 当类加载到JVM的时候,执行数据源的初始化
static {
MysqlDataSource mysqlDataSource = new MysqlDataSource();
mysqlDataSource.setURL(URL);
mysqlDataSource.setUser(USER);
mysqlDataSource.setPassword(PASSWORD);
dataSource = mysqlDataSource;
}
- 将构造方法
private DBUtil()私有化,防止外部通过new创建DBUtil实例。因为工具类的方法通常是静态的(如getConnection()、close()),不需要实例化对象即可调用,私有化构造方法能避免不必要的对象创建,节省资源。
3.获取数据库的连接
java
/**
* 获取数据库连接
* @return
* @throws SQLException
*/
public static Connection getConnection () throws SQLException {
return dataSource.getConnection();
}
- 封装
getConnection()方法,通过数据源dataSource.getConnection()获取连接,对外隐藏连接获取的细节(如 URL、用户名密码的配置)。调用者无需关心连接的具体参数,直接调用方法即可拿到连接,降低使用成本。 - 如果不在方法上声明
throws SQLException,就必须在方法内部用try-catch捕获异常。
4.释放资源,关闭连接
java
/**
* 释放资源,关闭连接
* @param resultSet
* @param statement
* @param connection
*/
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();
}
}
}
- 提供
close()方法,统一处理ResultSet、Statement、Connection三种资源的关闭。这三个对象是数据库操作中最常见的资源,若不及时关闭会导致连接泄露、数据库连接耗尽等问题。 - 关闭逻辑按 "先打开后关闭" 的顺序(
ResultSet→Statement→Connection),每个资源关闭前先判断是否为null,避免空指针异常,确保资源释放的安全性。
4.插入信息
1.获取数据库连接
java
Connection connection = null;
PreparedStatement statement = null;
// 插入操作需不需要定义结果集对象? -- 不用,因为insert返回的是受影响的行数
2.定义SQL 和预处理
java
// 1. 获取数据库连接
connection = DBUtil.getConnection();
// 2. 定义SQL
String sql = "insert into student (sn, name, mail, class_id) values (?,?,?,?)";
// 3. 定义SQL预处理对象
statement = connection.prepareStatement(sql);
3.接收用户参数
java
// 4. 接收用户参数
System.out.println("请输入学号:");
Scanner scanner = new Scanner(System.in);
String sn = scanner.next();
System.out.println("请输入姓名:");
String name = scanner.next();
System.out.println("请输入邮箱:");
String mail = scanner.next();
System.out.println("请输入班级编号:");
Long classId = Long.valueOf(scanner.next());
4.用真实数据替换占位符
java
// 5. 用真实数据填充占位符
statement.setString(1, sn);
statement.setString(2, name);
statement.setString(3, mail);
statement.setLong(4, classId);
// 6. 执行SQL获取结果
int row = statement.executeUpdate();
// 7. 判断结果
if (row == 1) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
row 这个变量代表的是 SQL 语句执行后影响的行数
SQL 插入语句的话一定会产生语句的影响,看语句的判读只要大于1,那就产生变化
5.关闭资源
java
finally {
// 释放资源,关闭连接
DBUtil.close(null, statement, connection);
}
调用的方法去关闭资源。
java
public class Demo03_Insert {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement statement = null;
// 插入操作需不需要定义结果集对象? -- 不用,因为insert返回的是受影响的行数
try {
// 1. 获取数据库连接
connection = DBUtil.getConnection();
// 2. 定义SQL
String sql = "insert into student (sn, name, mail, class_id) values (?,?,?,?)";
// 3. 定义SQL预处理对象
statement = connection.prepareStatement(sql);
// 4. 接收用户参数
System.out.println("请输入学号:");
Scanner scanner = new Scanner(System.in);
String sn = scanner.next();
System.out.println("请输入姓名:");
String name = scanner.next();
System.out.println("请输入邮箱:");
String mail = scanner.next();
System.out.println("请输入班级编号:");
Long classId = Long.valueOf(scanner.next());
// 5. 用真实数据填充占位符
statement.setString(1, sn);
statement.setString(2, name);
statement.setString(3, mail);
statement.setLong(4, classId);
// 6. 执行SQL获取结果
int row = statement.executeUpdate();
// 7. 判断结果
if (row == 1) {
System.out.println("插入成功");
} else {
System.out.println("插入失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 释放资源,关闭连接
DBUtil.close(null, statement, connection);
}
}
}