JDBC (Java Database Connectivity)
无论你使用什么数据库(MySQL, PostgreSQL, Oracle, SQL Server 等),Java 提供的标准 API 都是 JDBC,你可以把它想象成一座连接 Java 应用程序和数据库的“桥梁”。

获取数据的通用流程如下:
- 加载驱动:告诉 JVM 你要使用哪个数据库的驱动程序。
- 建立连接:通过 URL、用户名和密码,与数据库建立一个通信通道。
- 创建语句:创建一个
Statement或PreparedStatement对象,用于执行 SQL 查询。 - 执行查询:执行 SQL 语句,并返回一个
ResultSet对象,ResultSet就像一个指向查询结果集的游标。 - 处理结果集:遍历
ResultSet,从中取出每一行数据,并转换成 Java 对象(如自定义实体类、Map等)。 - 关闭资源:按照“后开先关”的原则,依次关闭
ResultSet、Statement和Connection。
传统 JDBC 方式(不推荐用于生产)
这是最基础、最原始的方式,能帮助你理解底层原理。但在实际项目中,我们不推荐直接使用,因为它代码冗长、繁琐且容易出错(比如忘记关闭资源)。
步骤详解
-
准备数据库驱动
- 下载你所用数据库的 JDBC 驱动 JAR 包(MySQL 的
mysql-connector-j-x.x.x.jar)。 - 将 JAR 包添加到你的项目的类路径(Classpath)中,如果你使用 Maven 或 Gradle,只需在
pom.xml或build.gradle中添加依赖即可。
Maven 依赖示例 (MySQL):
(图片来源网络,侵删)<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.33</version> <!-- 使用你需要的版本 --> </dependency> - 下载你所用数据库的 JDBC 驱动 JAR 包(MySQL 的
-
编写 Java 代码
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JdbcExample { // 数据库连接信息 private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC"; private static final String USER = "your_username"; private static final String PASS = "your_password"; public static void main(String[] args) { // try-with-resources 语句,可以自动关闭资源,是 Java 7+ 的最佳实践 try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT id, name, email FROM users")) { // 4. 处理结果集 System.out.println("ID\tName\tEmail"); while (rs.next()) { // 通过列名或列索引获取数据 int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); System.out.println(id + "\t" + name + "\t" + email); } } catch (SQLException e) { e.printStackTrace(); } // Connection, Statement, ResultSet 会在 try 块结束时自动关闭 } }
使用 try-with-resources 优化(推荐)
上面的代码已经使用了 try-with-resources,这是对传统 JDBC 最重要的优化,它能确保 Connection, Statement, ResultSet 等实现了 AutoCloseable 接口的资源在使用完毕后自动关闭,即使发生异常也不会导致资源泄漏。
使用 PreparedStatement 防止 SQL 注入(必备技能)
当 SQL 查询包含用户输入时,必须使用 PreparedStatement 来防止 SQL 注入攻击,它预编译 SQL 语句,然后将参数作为变量传入,数据库引擎不会将其解释为 SQL 代码。
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class PreparedStatementExample {
private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public List<String> findUsersByName(String nameKeyword) {
List<String> userList = new ArrayList<>();
// 使用 ? 作为占位符
String sql = "SELECT name FROM users WHERE name LIKE ?";
// try-with-resources 确保 Connection, PreparedStatement, ResultSet 自动关闭
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置参数,索引从 1 开始
pstmt.setString(1, "%" + nameKeyword + "%");
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
userList.add(rs.getString("name"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return userList;
}
}
使用连接池(生产环境标准)
每次获取数据库连接都创建一个新的,开销很大,连接池(Connection Pool)可以复用已经建立的连接,大大提高性能。

- HikariCP: 目前性能最好、最流行的连接池。
- Druid: 阿里开源,功能强大,带有监控功能。
使用 HikariCP 的示例:
-
添加 Maven 依赖
<dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> <!-- 使用最新版本 --> </dependency> -
配置并使用连接池
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import java.sql.*; import java.util.ArrayList; import java.util.List; public class DataSourceExample { // 1. 创建并配置数据源 private static HikariDataSource dataSource; static { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC"); config.setUsername("your_username"); config.setPassword("your_password"); config.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 连接池优化配置 (可选) config.setMaximumPoolSize(10); config.setMinimumIdle(5); config.setConnectionTimeout(30000); // 30 seconds config.setIdleTimeout(600000); // 10 minutes config.setMaxLifetime(1800000); // 30 minutes dataSource = new HikariDataSource(config); } public List<User> getAllUsers() { List<User> users = new ArrayList<>(); String sql = "SELECT id, name, email FROM users"; // try-with-resources 从连接池获取连接 try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setEmail(rs.getString("email")); users.add(user); } } catch (SQLException e) { e.printStackTrace(); } return users; } // 假设的 User 类 static class User { private int id; private String name; private String email; // Getters and Setters... } }
使用 ORM 框架(现代企业级开发首选)
对象关系映射框架让你可以用面向对象的方式来操作数据库,而不用写繁琐的 SQL 语句,框架会自动将 Java 对象映射到数据库表,并处理增删改查。
- MyBatis: SQL 与代码分离,SQL 语句写在 XML 文件中,灵活性高。
- Hibernate (JPA): 全自动 ORM,非常强大,但有时会显得“黑盒”。
- Spring Data JPA: 在 Hibernate 基础上封装,提供了极其简单的 Repository 接口,只需定义接口方法名即可实现查询,是 Spring Boot 生态中的绝对主流。
Spring Data JPA 示例 (最简单、最推荐)
这是目前 Java Web 开发中最主流、最高效的方式。
-
添加依赖 (Spring Boot 项目)
<!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> -
配置
application.propertiesspring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC spring.datasource.username=your_username spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA/Hibernate 配置 spring.jpa.hibernate.ddl-auto=update # 或 validate, create, create-drop spring.jpa.show-sql=true # 在控制台打印 SQL spring.jpa.properties.hibernate.format_sql=true # 格式化 SQL
-
创建实体类
import javax.persistence.*; @Entity // 声明这是一个 JPA 实体 @Table(name = "users") // 对应数据库中的 users 表 public class User { @Id // 声明主键 @GeneratedValue(strategy = GenerationType.IDENTITY) // 自增主键 private Long id; @Column(name = "name") // 对应 name 列 private String name; @Column(name = "email") private String email; // Getters and Setters... } -
创建 Repository 接口
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository // 声明这是一个 Spring Bean public interface UserRepository extends JpaRepository<User, Long> { // Spring Data JPA 会自动为你实现这个方法! // 根据方法名自动生成 SQL: SELECT * FROM users WHERE name LIKE ?% List<User> findByNameStartingWith(String namePrefix); } -
在 Service 中使用
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getAllUsers() { // findAll() 是 JpaRepository 提供的内置方法 return userRepository.findAll(); } public List<User> findUsersByName(String prefix) { // 直接调用我们自己定义的方法 return userRepository.findByNameStartingWith(prefix); } }
总结与建议
| 方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 传统 JDBC | 无需额外依赖,理解底层原理 | 代码繁琐,易出错,性能低 | 学习 JDBC 原理,简单脚本 |
PreparedStatement |
防止 SQL 注入,是必备技能 | 仍需手动管理资源 | 所有需要拼接 SQL 的场景 |
| 连接池 | 大幅提升性能,复用连接 | 需要额外配置和管理 | 所有生产环境 |
| ORM 框架 | 开发效率高,代码简洁,面向对象 | 学习曲线,有一定性能开销,SQL 灵活性降低 | 现代企业级应用开发 |
给新手的建议:
- 从
try-with-resources和PreparedStatement开始,这是写健壮 JDBC 代码的基础。 - 立刻使用连接池,HikariCP,这是生产环境的标配。
- 直接学习 Spring Data JPA,如果你使用 Spring Boot,这是最高效、最主流的选择,能让你从繁琐的 JDBC 代码中解放出来,专注于业务逻辑。
