我们将使用 JDBC (Java Database Connectivity),这是 Java 官方提供的用于执行 SQL 语句的 API,为了简化数据库连接管理,我们会引入一个流行的数据库连接池工具 HikariCP。

第一步:环境准备
在开始编码之前,请确保你已经准备好以下环境:
- Java 开发环境: JDK 8 或更高版本。
- MySQL 数据库: 安装并运行 MySQL 服务。
- MySQL 驱动: JDBC 驱动程序,用于 Java 连接 MySQL,你可以从 Maven 中央仓库 下载。
- IDE: 如 IntelliJ IDEA, Eclipse 等。
第二步:创建数据库和表
在 MySQL 中创建一个测试数据库和一张 users 表。
-- 创建数据库
CREATE DATABASE javadb;
-- 使用数据库
USE javadb;
-- 创建 users 表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
age INT
);
-- 插入一些初始数据
INSERT INTO users (name, email, age) VALUES
('张三', 'zhangsan@example.com', 25),
('李四', 'lisi@example.com', 30),
('王五', 'wangwu@example.com', 28);
第三步:项目配置 (Maven)
如果你使用 Maven 来管理项目,请在 pom.xml 文件中添加 MySQL 驱动和 HikariCP 的依赖。
<dependencies>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version> <!-- 使用你需要的版本 -->
</dependency>
<!-- HikariCP 连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version> <!-- 使用你需要的版本 -->
</dependency>
</dependencies>
第四步:创建数据库连接工具类
这是一个最佳实践,我们将数据库连接的创建和管理封装在一个工具类中,使用 HikariCP 连接池来提高性能和稳定性。

DBUtil.java
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DBUtil {
// 使用 HikariCP 创建数据源
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
// JDBC URL 格式: jdbc:mysql://[主机名]:[端口]/[数据库名]?[参数]
config.setJdbcUrl("jdbc:mysql://localhost:3306/javadb?useSSL=false&serverTimezone=UTC");
config.setUsername("root"); // 你的 MySQL 用户名
config.setPassword("your_password"); // 你的 MySQL 密码
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 连接池配置 (可选,但推荐)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
config.setIdleTimeout(600000); // 空闲超时时间 (毫秒)
config.setMaxLifetime(1800000); // 连接最大存活时间 (毫秒)
dataSource = new HikariDataSource(config);
}
/**
* 从连接池获取一个数据库连接
* @return Connection 对象
* @throws SQLException 如果获取连接失败
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
/**
* 关闭 Connection (实际上是将连接放回连接池)
* @param connection 要关闭的连接
*/
public static void closeConnection(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
第五步:实现增、删、改、查 操作
我们创建一个 UserDAO (Data Access Object) 类来封装所有的数据库操作。
UserDAO.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDAO {
// 1. 查询所有用户 (Read - 查询)
public List<User> getAllUsers() {
List<User> users = new ArrayList<>();
String sql = "SELECT id, name, email, age FROM users";
// try-with-resources 语句确保资源自动关闭
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
int age = rs.getInt("age");
users.add(new User(id, name, email, age));
}
} catch (SQLException e) {
e.printStackTrace();
}
return users;
}
// 2. 根据 ID 查询用户 (Read - 查询)
public User getUserById(int id) {
String sql = "SELECT id, name, email, age FROM users WHERE id = ?";
User user = null;
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置 SQL 语句中的参数
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
String name = rs.getString("name");
String email = rs.getString("email");
int age = rs.getInt("age");
user = new User(id, name, email, age);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return user;
}
// 3. 添加用户 (Create - 新增)
public boolean addUser(User user) {
String sql = "INSERT INTO users (name, email, age) VALUES (?, ?, ?)";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, user.getName());
pstmt.setString(2, user.getEmail());
pstmt.setInt(3, user.getAge());
// executeUpdate() 返回受影响的行数
int affectedRows = pstmt.executeUpdate();
return affectedRows > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 4. 更新用户 (Update - 修改)
public boolean updateUser(User user) {
String sql = "UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, user.getName());
pstmt.setString(2, user.getEmail());
pstmt.setInt(3, user.getAge());
pstmt.setInt(4, user.getId());
int affectedRows = pstmt.executeUpdate();
return affectedRows > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 5. 删除用户 (Delete - 删除)
public boolean deleteUser(int id) {
String sql = "DELETE FROM users WHERE id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
int affectedRows = pstmt.executeUpdate();
return affectedRows > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}
第六步:创建实体类
为了方便操作数据,我们创建一个 User 实体类来映射数据库中的 users 表。

User.java
public class User {
private int id;
private String name;
private String email;
private int age;
// 构造方法
public User() {}
public User(int id, String name, String email, int age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
// Getter 和 Setter 方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
第七步:测试
我们创建一个 Main 类来测试我们实现的 CRUD 功能。
Main.java
import java.util.List;
public class Main {
public static void main(String[] args) {
UserDAO userDAO = new UserDAO();
// 1. 查询并打印所有用户
System.out.println("--- 查询所有用户 ---");
List<User> allUsers = userDAO.getAllUsers();
allUsers.forEach(System.out::println);
// 2. 添加一个新用户
System.out.println("\n--- 添加新用户 ---");
User newUser = new User(0, "赵六", "zhaoliu@example.com", 35);
boolean isAdded = userDAO.addUser(newUser);
if (isAdded) {
System.out.println("用户添加成功!");
// 添加成功后重新查询以确认
allUsers = userDAO.getAllUsers();
allUsers.forEach(System.out::println);
}
// 3. 更新用户信息
System.out.println("\n--- 更新用户信息 ---");
if (!allUsers.isEmpty()) {
User userToUpdate = allUsers.get(0); // 获取第一个用户进行更新
userToUpdate.setAge(26);
userToUpdate.setEmail("zhangsan_new@example.com");
boolean isUpdated = userDAO.updateUser(userToUpdate);
if (isUpdated) {
System.out.println("用户更新成功!");
allUsers = userDAO.getAllUsers();
allUsers.forEach(System.out::println);
}
}
// 4. 根据 ID 查询用户
System.out.println("\n--- 根据 ID 查询用户 ---");
if (!allUsers.isEmpty()) {
int userIdToFind = allUsers.get(0).getId();
User foundUser = userDAO.getUserById(userIdToFind);
System.out.println("查找到的用户: " + foundUser);
}
// 5. 删除用户
System.out.println("\n--- 删除用户 ---");
if (!allUsers.isEmpty()) {
// 删除最后一个添加的用户 (赵六)
int userIdToDelete = newUser.getId();
boolean isDeleted = userDAO.deleteUser(userIdToDelete);
if (isDeleted) {
System.out.println("用户删除成功!");
allUsers = userDAO.getAllUsers();
allUsers.forEach(System.out::println);
}
}
}
}
运行结果
运行 Main.java,你将在控制台看到类似以下的输出(ID 和顺序可能略有不同):
--- 查询所有用户 ---
User{id=1, name='张三', email='zhangsan@example.com', age=25}
User{id=2, name='李四', email='lisi@example.com', age=30}
User{id=3, name='王五', email='wangwu@example.com', age=28}
--- 添加新用户 ---
用户添加成功!
User{id=1, name='张三', email='zhangsan@example.com', age=25}
User{id=2, name='李四', email='lisi@example.com', age=30}
User{id=3, name='王五', email='wangwu@example.com', age=28}
User{id=4, name='赵六', email='zhaoliu@example.com', age=35}
--- 更新用户信息 ---
用户更新成功!
User{id=1, name='张三', email='zhangsan_new@example.com', age=26}
User{id=2, name='李四', email='lisi@example.com', age=30}
User{id=3, name='王五', email='wangwu@example.com', age=28}
User{id=4, name='赵六', email='zhaoliu@example.com', age=35}
--- 根据 ID 查询用户 ---
查找到的用户: User{id=1, name='张三', email='zhangsan_new@example.com', age=26}
--- 删除用户 ---
用户删除成功!
User{id=1, name='张三', email='zhangsan_new@example.com', age=26}
User{id=2, name='李四', email='lisi@example.com', age=30}
User{id=3, name='王五', email='wangwu@example.com', age=28}
总结与最佳实践
- 使用
PreparedStatement: 始终使用PreparedStatement来执行 SQL 语句,它可以有效防止 SQL 注入攻击,并且对于需要重复执行的 SQL 语句,性能更高。 - 使用
try-with-resources: Java 7 引入了try-with-resources语句,它能自动实现Closeable资源(如Connection,PreparedStatement,ResultSet)的关闭,即使在try块中发生异常,也能确保资源被正确释放,避免了资源泄漏。 - 连接池: 在实际生产环境中,绝对不要每次操作都创建和销毁连接,使用 HikariCP 这样的连接池可以复用数据库连接,极大地提升性能和稳定性。
- DAO 模式: 将数据库操作逻辑与业务逻辑分离(
UserDAO负责 CRUD,Main负责业务流程),使代码结构更清晰,更易于维护和测试。 - 异常处理: 对数据库操作可能抛出的
SQLException进行适当的处理(如打印日志、抛出自定义异常等),不要简单地忽略它。
