1. 创建数据源
1.1 什么是数据源
- 数据源(DataSource) 用于管理数据库连接信息,通过数据源可以获取与 MySQL 数据库的连接对象
Connection。 - 在 JDBC 中,使用
MysqlDataSource配置数据库连接地址、用户名和密码。 - 先启动 MySQL 服务,再执行 Java 程序,否则可能出现连接失败。
- JDBC URL 中的数据库名称必须正确,且数据库需要事先创建。
DataSource是接口,MysqlDataSource是 MySQL 驱动提供的实现类。接口变量不能直接调用实现类特有的setUrl()、setUser()和setPassword()方法。- 数据库连接地址、用户名和密码必须与本机配置一致。
- 使用 JDBC 前,需要在项目中引入 MySQL Connector/J 驱动,否则可能出现找不到驱动类的错误。
1.2 导入相关类
java
import javax.sql.DataSource;
//数据库接口,mysql/sqlsever等多种数据库,用的使用要向上/下转型
import com.mysql.cj.jdbc.MysqlDataSource;
//这里使用的是mysql数据库。MysqlDataSource是DataSource其中一个子类
import java.sql.Connection;
//数据库连接类
import java.sql.SQLException;
//sql语句会有异常,所以包导入异常类
1.3 创建并配置数据源
java
// 1. 创建数据源对象
DataSource dataSource = new MysqlDataSource();
//使用mysql数据库子类,向上转型为DataSource类
// 2. 配置数据库连接地址
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java119?characterEncoding=utf8&useSSL=false");
//(MysqlDataSource)dataSource:将dataSource对象强转成MysqlDataSource类,调用MysqlDataSource子类中特有的setUrl方法,设置要访问的数据库地址,编码集,私密性
// 3. 设置数据库用户名
((MysqlDataSource) dataSource).setUser("root");
// 4. 设置数据库密码
((MysqlDataSource) dataSource).setPassword("2222");
// 5. 获取数据库连接对象
Connection connection = dataSource.getConnection();
/*
DataSource:连接配置保存数据库地址、账号和密码等信息。
Connection:通信通道建立 Java 程序与 MySQL 之间的连接,让程序能够提交 SQL。
PreparedStatement:SQL 执行工具,通过连接创建,用来设置 SQL 参数并执行 SQL。
*/
1.4 JDBC URL 组成
java
jdbc:mysql://127.0.0.1:3306/java119?characterEncoding=utf8&useSSL=false
| 组成部分 | 含义 |
|---|---|
jdbc:mysql |
使用 MySQL 的 JDBC 驱动 |
127.0.0.1 |
数据库服务器地址,本机 IP |
3306 |
MySQL 默认端口 |
java119 |
要连接的数据库名称 |
characterEncoding=utf8 |
指定字符编码 |
useSSL=false |
禁用 SSL 连接,私密,禁止他人访问 |
2. 构造 SQL 语句
2.1 获取用户输入
- 使用
Scanner获取用户输入的学号和姓名。
java
import java.util.Scanner;
// 创建输入对象
Scanner scanner = new Scanner(System.in);
// 输入学号
System.out.println("请输入学号:");
int id = scanner.nextInt();
// 输入姓名
System.out.println("请输入姓名:");
String name = scanner.next();
2.2 SQL 语句的构造方式
方式一:直接编写固定 SQL
java
String sql = "INSERT INTO student VALUES (4, '赵六')";
- 这种方式适用于固定数据,但无法直接满足动态输入的需求。
方式二:字符串拼接
java
String sql = "INSERT INTO student VALUES ( " + id + " , ' " + name + " ' )";
// 4, '赵六'
- 这种方式可以将用户输入拼接到 SQL 中,但存在 SQL 注入风险,并且需要注意字符串引号问题。
方式三:使用占位符(推荐)
java
String sql = "INSERT INTO student VALUES (?, ?)";
java? :代表占位符,数据库表中第一列是id第一个?就代表id列。
- 第一个
?表示学号。 - 第二个
?表示姓名。 - 使用占位符可以将 SQL 结构与具体参数分开,后续通过
PreparedStatement绑定参数。
-
SQL 语句中的表名、字段名必须与数据库实际结构一致。
-
使用
INSERT INTO student VALUES (?, ?)时,参数顺序必须与表中字段的顺序一致。 -
如果只插入指定字段,推荐明确写出字段名:
javascriptString sql = "INSERT INTO student (id, name) VALUES (?, ?)";这样可以避免因表字段顺序变化而导致插入错误。
-
SQL 字符串拼接虽然可以动态生成 SQL,但不推荐直接拼接用户输入的数据,容易引发 SQL 注入问题。
-
PreparedStatement中的?用于表示参数值,不能直接代替表名、字段名或 SQL 关键字。
3. 预处理 SQL 语句
3.1 创建 PreparedStatement 对象
PreparedStatement是 JDBC 提供的预处理 SQL 语句对象,可以设置 SQL 参数并执行 SQL。
java
import java.sql.PreparedStatement;
PreparedStatement statement = connection.prepareStatement(sql)
/*
将上述写的sql语句当成参数传进来进行预处理
根据 SQL 创建预处理语句对象:statement
connection:已经建立的数据库连接对象。
prepareStatement(sql):调用方法,创建并返回一个预处理语句对象。
statement:引用这个返回的对象,后续通过它设置参数和执行 SQL。
*/
- 这里的
connection是前面通过数据源获取的数据库连接对象,sql是包含占位符的 INSERT INTO student VALUES (?, ?)语句。
3.2 设置占位符参数
java
// 设置第一个占位符,学号从 1 开始编号
statement.setInt(1, id);
// 设置第二个占位符,姓名从 2 开始编号
statement.setString(2, name);
常用参数设置方法:
| 方法 | 作用 |
|---|---|
setInt(index, value) |
设置整数参数 |
setString(index, value) |
设置字符串参数 |
setDouble(index, value) |
设置双精度浮点数参数 |
setBoolean(index, value) |
设置布尔参数 |
setNull(index, sqlType) |
设置 SQL 空值 |
注意: PreparedStatement 的参数下标从 1 开始,而不是从 0 开始。
3.3 预处理的优点
-
提高安全性: 使用参数绑定能够有效防范通过参数值进行的 SQL 注入。
-
方便传参: 无需手动拼接字符串和处理引号。
-
便于维护: SQL 结构与参数分离,代码更加清晰。
-
参数下标从 1 开始,而不是从 0 开始。
javastatement.setInt(1, id); statement.setString(2, name); -
参数设置方法需要与 Java 数据类型相匹配,例如整数使用
setInt(),字符串使用setString()。 -
占位符的数量必须与实际绑定的参数数量对应。
-
参数绑定必须在执行 SQL 之前完成,否则可能出现参数未设置的异常。
-
使用
PreparedStatement绑定参数能够有效防范 SQL 注入,但前提是将用户输入作为参数绑定,而不是先拼接进 SQL 字符串。
4. 将 SQL 语句发送到数据库服务器并执行
executeUpdate()不用于读取查询结果集。 执行SELECT查询通常使用executeQuery()。executeUpdate()返回受影响的记录数,不是布尔值,也不是查询结果。- 返回值为
1通常表示成功插入或修改了一条记录;返回值为0不一定表示程序报错,例如某些更新语句没有匹配到记录时就可能返回0。 - 如果插入的主键已经存在,可能出现主键重复异常;如果字段不允许为空,也需要确保传入的数据满足约束。
- SQL 执行失败时,通常会抛出
SQLException,应通过异常处理定位问题。
4.1 执行 预处理后的SQL语句
java
// 执行 INSERT、UPDATE、DELETE 等数据修改语句
int n = statement.executeUpdate();
// 输出受影响的记录数
System.out.println("n = " + n);
executeUpdate()用于执行INSERT、UPDATE、DELETE等数据修改语句,也可以执行建表等不返回查询结果集的 SQL。- 返回值
n通常表示受影响的记录数。例如,插入一条学生记录时,成功插入一条通常返回1。
4.2 JDBC 常见执行方法
| 方法 | 适用场景 | 返回值 |
|---|---|---|
executeQuery() |
SELECT 查询 |
ResultSet 结果集 |
executeUpdate() |
INSERT、UPDATE、DELETE 等 |
int 受影响行数 |
execute() |
不确定 SQL 类型或需要通用执行 | boolean,表示是否返回结果集 |
执行流程:
- 将 SQL 语句交给
Connection创建PreparedStatement。 - 使用
setInt()、setString()等方法绑定参数。 - 调用
executeUpdate()执行语句。 - JDBC 驱动与数据库服务器通信,数据库执行 SQL 并返回执行结果。
5. 资源回收
5.1 为什么需要资源回收
- JDBC 操作过程中会创建数据库连接和 SQL 语句对象。这些对象占用数据库连接、服务器会话或其他资源,因此使用结束后应及时释放。
java
// 关闭 SQL 语句对象
statement.close();
// 关闭数据库连接
connection.close();
-
原始示例还创建了
Scanner,如果不再使用,也可以关闭:scanner.close();
6. JDBC 操作 MySQL 完整示例
6.1插入语句
java
import com.mysql.cj.jdbc.MysqlDataSource;// 导入 MySQL 数据源实现类,用于配置 MySQL 数据库连接
import javax.sql.DataSource;// 导入数据源接口,用于获取数据库连接
import java.sql.Connection;// 导入数据库连接接口,负责创建 SQL 语句对象和管理事务
import java.sql.PreparedStatement;// 导入预处理 SQL 语句接口,用于绑定参数和执行 SQL
import java.sql.SQLException;// 导入 SQL 异常类,用于处理数据库操作过程中发生的异常
import java.util.Scanner;
public class JdbcDemo {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
// 1. 创建并配置 "数据源"
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java119?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("2222");
// 2. 依据上面的数据源, 对数据库服务器, 建立连接
Connection connection = dataSource.getConnection();
System.out.println("请输入学号: ");
int id = scanner.nextInt();
System.out.println("请输入姓名: ");
String name = scanner.next();
//3.构造sql语句
String sql = "insert into student values(?, ?)";
// 4.预处理:把 SQL 字符串转为 "sql语句对象"
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, id);
statement.setString(2, name);
// 5. 执行语句对象 (把预处理过的 SQL 发送给数据库服务器)
int n = statement.executeUpdate();
System.out.println("n = " + n);
// 6. 释放前面创建过的资源.
statement.close();
connection.close();
}
}
本程序的执行步骤
- 创建数据源: 配置数据库地址、用户名和密码。
- 获取连接: 通过
getConnection()获取数据库连接对象。 - 接收输入: 获取学生的学号和姓名。
- 构造 SQL: 使用
?占位符编写插入语句。 - 预处理和绑定参数: 创建
PreparedStatement,将输入数据绑定到占位符。 - 执行 SQL: 调用
executeUpdate()插入数据。 - 释放资源: 关闭语句对象、数据库连接和输入对象。
注意
Connection和PreparedStatement如果执行过程中发生异常,原代码可能无法执行到close()。INSERT INTO student VALUES (?, ?)默认按表的字段顺序插入数据。更推荐明确写出字段名,例如INSERT INTO student (id, name) VALUES (?, ?)。setInt(1, id)中的1是占位符的位置,不是学号;真正的学号来自变量id。executeUpdate()返回的是受影响的记录数int类型,不是新插入记录的学号。
运行前提:
- 已添加 MySQL Connector/J 驱动依赖。
- MySQL 服务已经启动。
java119数据库和student表已经存在。student表的字段顺序与插入的学号、姓名对应。- 数据库用户名、密码与本机实际配置一致。
6.2查询语句
java
import com.mysql.cj.jdbc.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class JdbcDemo {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
// 1. 创建并配置 "数据源"
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java119?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("2222");
// 2. 依据上面的数据源, 对数据库服务器, 建立连接
Connection connection = dataSource.getConnection();
System.out.println("请输入学号: ");
int id = scanner.nextInt();
System.out.println("请输入姓名: ");
String name = scanner.next();
// 3. 构造 SQL
// String sql = "insert into student values(4, \"赵六\")";
// String sql = "insert into student values(" + id + ", \"" + name + "\")";
// System.out.println("拼装好的 SQL 为: " + sql);
String sql = "insert into student values(?, ?)";
// 4.预处理:实际上还需要把 SQL 字符串转为 "语句对象"
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, id);
statement.setString(2, name);
// 5. 执行这个语句对象 (把预处理过的 SQL 发送给数据库服务器)
int n = statement.executeUpdate();
System.out.println("n = " + n);
// 6. 释放前面创建过的资源.
statement.close();
connection.close();
}
}
7. 本节总结
| 步骤 | 核心对象或方法 | 作用 |
|---|---|---|
| 1. 创建数据源 | DataSource、MysqlDataSource |
配置数据库连接信息 |
| 2. 构造 SQL | String sql |
定义要执行的 SQL 语句 |
| 3. 预处理 | prepareStatement()、setInt()、setString() |
创建语句对象并绑定参数 |
| 4. 执行 SQL | executeUpdate() |
将语句交由 JDBC 驱动执行并获取结果 |
| 5. 资源回收 | close()、try-with-resources |
释放语句对象、数据库连接等资源 |
记忆口诀: 创建数据源 → 构造 SQL → 预处理并绑定参数 → 执行 SQL → 释放资源。
8. 常见错误与排查
| 常见问题 | 可能原因 | 排查方法 |
|---|---|---|
找不到 MysqlDataSource |
未引入 MySQL 驱动依赖 | 检查 Connector/J 依赖 |
| 数据库连接失败 | MySQL 未启动、URL 错误或账号密码不正确 | 检查服务状态和连接配置 |
| 找不到数据库 | 数据库名称错误或数据库尚未创建 | 执行 SHOW DATABASES; |
| 找不到数据表 | 表名错误或表尚未创建 | 执行 SHOW TABLES; |
| 参数下标越界 | 使用了从 0 开始的参数编号 | 检查参数下标是否从 1 开始 |
| 参数未设置 | 存在未绑定的占位符 | 检查 ? 的数量及参数绑定 |
| 主键重复 | 插入了已经存在的主键 | 检查表中的主键数据 |
| SQL 执行异常 | SQL 语法错误、字段不匹配或违反约束 | 查看 SQLException 的异常信息 |
9.JDBC 中的 Connection 接口
9.1 Connection 的基本概念
Connection是 JDBC 提供的数据库连接接口,用于表示 Java 程序与数据库之间的连接,并提供创建 SQL 语句对象、管理事务等方法。
java
// 获取数据库连接对象
Connection connection = dataSource.getConnection();
Connection:数据库连接接口。connection:用于引用数据库连接对象的变量。dataSource:数据源对象,保存数据库连接配置信息。getConnection():获取数据库连接的方法。- 注意:
Connection是接口,不能直接使用new Connection()创建对象,通常通过DataSource获取其实现对象。
9.2 Connection 提供的主要方法
| 方法 | 作用 |
|---|---|
createStatement() |
创建 Statement 对象,用于执行 SQL |
prepareStatement(String sql) |
创建 PreparedStatement 对象,用于预处理 SQL |
prepareCall(String sql) |
创建 CallableStatement 对象,用于调用存储过程 |
commit() |
提交事务 |
rollback() |
回滚事务 |
setAutoCommit(boolean) |
设置是否自动提交事务 |
close() |
关闭连接,释放相关资源 |
9.3 三种 SQL 语句对象
9.3.1 Statement
- 创建普通 SQL 语句对象
- 类实现了接口,由这个类实例化的对象就可以调用接口中的方法。
java
// 创建普通 SQL 语句对象
Statement statement = connection.createStatement();
// 执行 SQL
int rows = statement.executeUpdate( "INSERT INTO student VALUES (1, '张三')" );
- 通过
createStatement()创建。 - 用于执行普通 SQL 语句。
- 不提供
PreparedStatement那样的参数绑定机制。
9.3.2 Connection 与其他 JDBC 对象的关系
java
DataSource
│
│ getConnection()
▼
Connection接口
│
├── createStatement():类中的方法
│ └── Statement类实现了Connection接口
│
├── prepareStatement(sql):类中的方法
└── PreparedStatement类实现了Connection接口
9.3.3 核心知识点
Connection是 JDBC 中的数据库连接接口。Connection提供createStatement()、prepareStatement()和prepareCall()等方法,用于创建不同的 SQL 语句对象。Connection可以通过commit()、rollback()和setAutoCommit()管理事务。PreparedStatement支持占位符和参数绑定,是常用的 SQL 执行方式。- 数据库操作完成后,应及时关闭
PreparedStatement和Connection。
注意:
DataSource是数据源接口,MysqlDataSource是 MySQL 驱动提供的实现类。由于接口中没有setUrl()、setUser()等方法,因此示例中需要将DataSource强制转换为MysqlDataSource才能调用这些方法。
10. JDBC 执行流程图
java
创建并配置 DataSource
↓
获取 Connection
↓
构造 SQL 字符串
↓
调用 prepareStatement()
↓
使用 setXxx() 绑定参数
↓
调用 executeUpdate() / executeQuery()//将预处理后的sql语句执行
↓
获取执行结果
↓
关闭 PreparedStatement
↓
关闭 Connection