核心概念:JDBC
在 Java 中,我们通过 JDBC (Java Database Connectivity) 来与数据库进行交互,JDBC 是 Java 提供的一套标准 API,它定义了一组规则和接口,允许 Java 程序执行 SQL 语句并处理结果。

你可以把 JDBC 想象成一个“翻译官”或“中间人”:
- Java 程序:说 Java 语言。
- MySQL 数据库:说 SQL 语言。
- JDBC:负责将 Java 的请求翻译成 SQL,发送给数据库,并将数据库返回的结果翻译成 Java 能理解的对象(如
ResultSet)。
准备工作
在开始编码之前,你需要准备好以下三样东西:
MySQL 数据库和表
确保你已经安装了 MySQL 数据库,并创建了一个数据库和一张用于测试的表。
-- 创建一个名为 `java_test` 的数据库
CREATE DATABASE java_test;
-- 使用该数据库
USE java_test;
-- 创建一个名为 `users` 的表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入一些测试数据
INSERT INTO users (username, password, email) VALUES
('alice', 'pass123', 'alice@example.com'),
('bob', 'bobpass', 'bob@example.com');
MySQL JDBC 驱动程序
Java 程序需要通过这个驱动才能与 MySQL 通信,你不需要手动下载 .jar 文件并添加到项目路径中,现代构建工具(如 Maven 或 Gradle)会自动处理。
Java 开发环境
一个标准的 Java 开发环境(JDK)和 IDE(如 IntelliJ IDEA 或 Eclipse)。
第一步:使用 Maven/Gradle 管理依赖
这是现代 Java 项目的标准做法,我们在 pom.xml (Maven) 或 build.gradle (Gradle) 文件中添加 MySQL 驱动的依赖。
Maven (pom.xml):
<dependencies>
<!-- MySQL Connector/J 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version> <!-- 建议使用最新稳定版 -->
</dependency>
</dependencies>
Gradle (build.gradle):
dependencies {
// MySQL Connector/J 驱动
implementation 'com.mysql:mysql-connector-j:8.0.33' // 建议使用最新稳定版
}
添加依赖后,你的构建工具会自动下载并配置好驱动。
第二步:编写 Java 代码进行数据库操作
我们将按照标准的步骤来编写代码,这些步骤是 JDBC 操作的通用流程。
加载驱动并建立连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class JdbcExample {
// 数据库连接信息
private static final String URL = "jdbc:mysql://localhost:3306/java_test?useSSL=false&serverTimezone=UTC";
private static final String USER = "root"; // 你的数据库用户名
private static final String PASSWORD = "your_password"; // 你的数据库密码
public static void main(String[] args) {
Connection connection = null;
try {
// 1. 加载驱动 (对于新版本的驱动,这步通常是可选的,但写上更明确)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 建立连接
System.out.println("正在连接数据库...");
connection = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功!");
// ... 在这里执行数据库操作 ...
} catch (ClassNotFoundException e) {
System.err.println("找不到 MySQL JDBC 驱动类。");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("数据库连接或操作失败。");
e.printStackTrace();
} finally {
// 3. 关闭连接 (非常重要!)
if (connection != null) {
try {
connection.close();
System.out.println("数据库连接已关闭。");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
代码解释:
- URL: 数据库的连接地址。
jdbc:mysql://: 协议和子协议。localhost:3306: 数据库服务器的地址和端口。/java_test: 要连接的数据库名。?useSSL=false&serverTimezone=UTC: 连接参数。useSSL=false用于禁用 SSL(本地开发时常用),serverTimezone=UTC指定时区,避免警告。
DriverManager.getConnection(): 这个静态方法会尝试使用所有已注册的驱动程序来建立连接。try-catch-finally: 这是处理数据库资源的标准模式。finally块确保无论是否发生异常,connection.close()都会被执行,以释放数据库资源。
第三步:执行 SQL 语句
连接建立后,我们就可以执行 SQL 语句了,主要有三种操作:查询、更新、批处理。
A. 查询操作 (SELECT)
使用 Statement 或 PreparedStatement 来执行查询。强烈推荐使用 PreparedStatement,因为它可以防止 SQL 注入攻击,并且性能更好。
// ... (接上面的 main 方法,在 try 块内)
// 4. 创建 PreparedStatement 对象
String sql = "SELECT id, username, email FROM users WHERE id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 5. 设置参数 (索引从 1 开始)
preparedStatement.setInt(1, 1); // 设置第一个参数为 id=1
// 6. 执行查询,获取结果集
ResultSet resultSet = preparedStatement.executeQuery();
// 7. 处理结果集
while (resultSet.next()) { // .next() 移动到下一行,如果存在则返回 true
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String email = resultSet.getString("email");
System.out.printf("ID: %d, 用户名: %s, 邮箱: %s%n", id, username, email);
}
// 8. 关闭资源
resultSet.close();
preparedStatement.close();
B. 更新操作 (INSERT, UPDATE, DELETE)
更新操作不返回 ResultSet,而是返回一个整数,表示受影响的行数。
// ... (接上面的 main 方法,在 try 块内)
// 插入新用户
String insertSql = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
PreparedStatement insertStatement = connection.prepareStatement(insertSql);
insertStatement.setString(1, "charlie");
insertStatement.setString(2, "charliepass");
insertStatement.setString(3, "charlie@example.com");
int rowsInserted = insertStatement.executeUpdate();
if (rowsInserted > 0) {
System.out.println("新用户插入成功!");
}
insertStatement.close();
// 更新用户信息
String updateSql = "UPDATE users SET email = ? WHERE username = ?";
PreparedStatement updateStatement = connection.prepareStatement(updateSql);
updateStatement.setString(1, "alice_new@example.com");
updateStatement.setString(2, "alice");
int rowsUpdated = updateStatement.executeUpdate();
if (rowsUpdated > 0) {
System.out.println("用户信息更新成功!");
}
updateStatement.close();
第四步:最佳实践 - 使用 try-with-resources (JDK 7+)
手动关闭 Connection, PreparedStatement, ResultSet 等资源非常繁琐,而且容易出错,JDK 7 引入了 try-with-resources 语句,它可以自动关闭实现了 AutoCloseable 接口(所有 JDBC 资源都实现了)的对象。
这是目前推荐的写法,代码更简洁、更安全。
import java.sql.*;
public class JdbcBestPractice {
private static final String URL = "jdbc:mysql://localhost:3306/java_test?useSSL=false&serverTimezone=UTC";
private static final String USER = "root";
private static final String PASSWORD = "your_password";
public static void main(String[] args) {
// try-with-resources 会自动关闭 connection, preparedStatement, resultSet
try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
PreparedStatement preparedStatement = connection.prepareStatement("SELECT id, username FROM users");
ResultSet resultSet = preparedStatement.executeQuery()) {
System.out.println("数据库连接成功,开始查询...");
while (resultSet.next()) {
System.out.println("ID: " + resultSet.getInt("id") +
", 用户名: " + resultSet.getString("username"));
}
} catch (SQLException e) {
System.err.println("数据库操作出错!");
e.printStackTrace();
}
// connection, preparedStatement, resultSet 都已自动关闭
}
}
第五步:高级主题 - 连接池
每次操作数据库都创建和销毁连接是非常消耗资源的。连接池 应运而生,它预先创建一组数据库连接,并将其缓存起来,当需要时,从池中获取一个用完后再放回池中,而不是销毁。
这极大地提高了性能和响应速度。
添加连接池依赖
Maven (pom.xml):
<!-- HikariCP 是目前性能最好的连接池之一 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
使用 HikariCP 创建和管理连接
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcWithPool {
// 创建一个静态的连接池数据源
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/java_test?useSSL=false&serverTimezone=UTC");
config.setUsername("root");
config.setPassword("your_password");
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 连接池优化配置 (可选)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
dataSource = new HikariDataSource(config);
}
public static void main(String[] args) {
// 从连接池获取一个连接
try (Connection connection = dataSource.getConnection();
PreparedStatement pstmt = connection.prepareStatement("SELECT username FROM users WHERE id = ?")) {
pstmt.setInt(1, 1);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
System.out.println("查询到的用户名: " + rs.getString("username"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
// 在应用程序关闭时,关闭连接池
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
}
}
}
第六步:现代框架 - JPA / MyBatis
虽然 JDBC 是基础,但在实际的企业级项目中,我们通常不会直接写这么多 JDBC 代码,而是使用 ORM(对象关系映射)框架或 SQL 映射框架来简化开发。
JPA (Java Persistence API) / Hibernate
- 理念: 让你用 Java 对象来操作数据库,框架会自动将其转换为 SQL,你几乎不需要写原生 SQL。
- 示例: 定义一个
User实体类,然后通过userRepository.findById(1L)来查询用户,代码非常面向对象。 - 优点: 开发效率高,代码可读性好,减少 SQL 书写量。
- 缺点: 对于复杂查询,可能不如手写 SQL 灵活和高效。
MyBatis
- 理念: 将 SQL 语句写在 XML 文件或注解中,Java 代码通过调用方法来执行这些预定义的 SQL。
- 示例: 在
UserMapper.xml中定义<select id="selectUserById">...</select>,然后在 Java 代码中调用userMapper.selectUserById(1)。 - 优点: SQL 与代码分离,便于维护和优化,对 SQL 的控制力非常强。
- 缺点: 需要额外维护 SQL 文件,开发量比 JPA 稍多。
| 技术层次 | 技术名称 | 描述 | 适用场景 |
|---|---|---|---|
| 基础 | JDBC | Java 官方提供的数据库操作标准 API。 | 学习原理、简单工具、无框架项目。 |
| 最佳实践 | JDBC + 连接池 | 在 JDBC 基础上,使用连接池(如 HikariCP)管理连接。 | 绝大多数 Java Web 应用的标准做法。 |
| 高级 | JPA / Hibernate | ORM 框架,用 Java 对象操作数据库。 | 快速开发,业务逻辑为主的项目。 |
| 高级 | MyBatis | SQL 映射框架,灵活控制 SQL。 | 对 SQL 性能和灵活性要求高的项目。 |
对于初学者,务必掌握 JDBC 的基本原理和 try-with-resources 的用法。学会使用连接池(如 HikariCP),这是从入门到进阶的关键一步,再根据项目需求学习 JPA 或 MyBatis 这样的框架。
