- 核心概念:JDBC 和 JDBC 驱动程序
- 环境准备:下载并配置 Oracle 驱动
- 核心代码示例:从建立连接到执行查询
- 最佳实践:使用
try-with-resources和PreparedStatement - 连接池 (Connection Pooling):提升性能的关键
- 常见问题与解决方案
核心概念:JDBC 和 JDBC 驱动程序
- JDBC (Java Database Connectivity):这是 Java 提供的一套标准 API,用于执行 SQL 语句,它定义了如何从 Java 程序连接到各种数据库、执行查询、获取结果等操作,你可以把它想象成 Java 和数据库之间的“通用翻译官”。
- JDBC 驱动程序 (Driver):数据库厂商(如 Oracle)提供的实现类,它负责将 JDBC 的标准调用“翻译”成该特定数据库能理解的协议,没有驱动,JDBC API 就无法与 Oracle 数据库通信。
对于 Oracle 数据库,我们通常使用 Oracle JDBC Thin Driver,这是一个纯 Java 的驱动,无需在客户端安装 Oracle 客户端软件,非常适合大多数应用场景。

环境准备:下载并配置 Oracle 驱动
在编写代码之前,你需要获取 Oracle JDBC 驱动的 JAR 包。
步骤 1: 下载驱动
最推荐的下载方式是使用 Maven 或 Gradle,这样可以自动管理依赖。
使用 Maven (推荐)
在你的 pom.xml 文件中添加以下依赖:

<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version> <!-- 请根据你的 Oracle 数据库版本选择合适的版本 -->
</dependency>
- 注意:
ojdbc8用于 Java 8 和更高版本,如果你的项目使用 Java 6 或 7,需要使用ojdbc7。
手动下载 JAR 包
如果你不使用 Maven,可以从 Oracle 官网或 Maven 中央仓库下载 JAR 包。
- Oracle 官网:你需要拥有 Oracle 帐号才能下载,搜索 "Oracle JDBC Driver"。
- Maven 中央仓库:https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8
下载后,将 JAR 文件添加到你的项目的类路径中。
步骤 2: 准备 Oracle 数据库
确保你有一个可用的 Oracle 数据库实例,并且你知道以下连接信息:
- URL: 格式通常为
jdbc:oracle:thin:@<host>:<port>:<service_name>host: 数据库服务器的 IP 地址或主机名 (如localhost或168.1.100)port: 数据库监听的端口 (默认为1521)service_name: 数据库的服务名 (SID 在较新版本中已不推荐使用),你可以通过 SQL*Plus 或 SQL Developer 查询。
- 用户名: 你的数据库用户名 (如
scott) - 密码: 你的数据库密码 (如
tiger)
核心代码示例
下面是一个完整的、可运行的 Java 示例,演示了如何连接到 Oracle 数据库、执行查询并处理结果。
示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class OracleJdbcExample {
// 数据库连接信息 - 请根据你的环境修改
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:ORCLCDB"; // 请替换为你的URL
private static final String USER = "your_username"; // 请替换为你的用户名
private static final String PASS = "your_password"; // 请替换为你的密码
public static void main(String[] args) {
// try-with-resources 语句,确保资源在使用后被自动关闭
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM EMP")) { // 假设你有一个EMP表
// 检查连接是否成功
if (conn != null) {
System.out.println("成功连接到 Oracle 数据库!");
}
// 遍历结果集
System.out.println("EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO");
System.out.println("------------------------------------------------------------------------");
while (rs.next()) {
// 通过列名获取数据,更具可读性且不易出错
int empno = rs.getInt("EMPNO");
String ename = rs.getString("ENAME");
String job = rs.getString("JOB");
int mgr = rs.getInt("MGR");
java.sql.Date hiredate = rs.getDate("HIREDATE");
double sal = rs.getDouble("SAL");
double comm = rs.getDouble("COMM");
int deptno = rs.getInt("DEPTNO");
System.out.printf("%-5d %-7s %-11s %-5d %-12s %-8.2f %-8.2f %d%n",
empno, ename, job, mgr, hiredate, sal, comm, deptno);
}
} catch (SQLException e) {
System.err.println("数据库操作失败!");
e.printStackTrace();
}
}
}
代码解析
- 加载驱动:在现代 JDBC (4.0+) 中,通常不需要显式调用
Class.forName("oracle.jdbc.OracleDriver"),当你调用DriverManager.getConnection()时,驱动管理器会自动在类路径中查找并加载合适的驱动。 - 建立连接:
DriverManager.getConnection(DB_URL, USER, PASS)是核心方法,它使用提供的 URL、用户名和密码建立与数据库的连接。 - 创建 Statement:
conn.createStatement()创建一个Statement对象,用于执行 SQL 语句。 - 执行查询:
stmt.executeQuery("SELECT ...")执行一个查询语句,并返回一个ResultSet对象,该对象包含了查询结果。 - 处理结果集:
rs.next(): 将光标移动到下一行,如果存在下一行则返回true。rs.getXXX("列名"): 根据列名获取当前行的数据,XXX是数据类型(如getInt,getString,getDate等),推荐使用列名而不是列索引。
- 关闭资源:
try-with-resources语句是 Java 7+ 的特性,它能确保Connection,Statement, 和ResultSet这些实现了AutoCloseable接口的资源在代码块执行完毕后自动被关闭,即使发生异常也是如此,这是防止资源泄漏的最佳实践。
最佳实践:使用 PreparedStatement
在上述示例中,我们使用了 Statement,但在实际开发中,强烈推荐使用 PreparedStatement,尤其是在执行带参数的 SQL 查询时。
为什么使用 PreparedStatement?
- 防止 SQL 注入:
PreparedStatement会对输入参数进行转义处理,从根本上杜绝了 SQL 注入的风险。 - 性能更优:数据库可以预编译
PreparedStatement的 SQL 语句,如果同一个 SQL 被多次执行(只是参数不同),数据库可以重用预编译的执行计划,提高效率。 - 代码更清晰:使用 作为占位符,代码更易读和维护。
使用 PreparedStatement 的示例
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class OraclePreparedStatementExample {
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:ORCLCDB";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void findEmployeeByName(String namePattern) {
// SQL 查询语句,使用 ? 作为参数占位符
String sql = "SELECT EMPNO, ENAME, JOB FROM EMP WHERE ENAME LIKE ?";
// try-with-resources 确保 conn, stmt, rs 都被关闭
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置参数,索引从 1 开始
pstmt.setString(1, "%" + namePattern + "%");
// 执行查询
try (ResultSet rs = pstmt.executeQuery()) {
System.out.println("查找名字包含 '" + namePattern + "' 的员工:");
System.out.println("EMPNO ENAME JOB");
System.out.println("--------------------");
while (rs.next()) {
System.out.printf("%-5d %-7s %s%n",
rs.getInt("EMPNO"), rs.getString("ENAME"), rs.getString("JOB"));
}
}
} catch (SQLException e) {
System.err.println("查询失败: " + e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
findEmployeeByName("SM");
}
}
连接池 (Connection Pooling)
每次需要数据库操作时都创建一个新的连接,是一个开销很大的过程,连接池技术就是为了解决这个问题而生的。
什么是连接池? 连接池是一个预先创建并维护一定数量的数据库连接对象的“池子”,当应用程序需要一个连接时,它从池中获取一个已存在的连接,用完后将其归还到池中,而不是关闭它,这样可以极大地减少连接创建和销毁的开销,显著提升应用性能。
常用的 Java 连接池库:
- HikariCP: 目前性能最好、最受欢迎的连接池,Spring Boot 2.x 默认使用它。
- Apache DBCP (Database Connection Pool): 一个经典的开源连接池实现。
- C3P0: 另一个老牌的连接池实现。
使用 HikariCP 的示例
添加 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.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class OracleWithHikariCPExample {
// 使用 HikariDataSource 作为连接池
private static HikariDataSource dataSource;
// 静态代码块,在类加载时初始化连接池
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:ORCLCDB");
config.setUsername("your_username");
config.setPassword("your_password");
config.setDriverClassName("oracle.jdbc.OracleDriver");
// 连接池配置 (可根据实际情况调整)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
config.setIdleTimeout(600000); // 空闲连接超时时间
config.setMaxLifetime(1800000); // 连接最大存活时间
dataSource = new HikariDataSource(config);
}
public static void main(String[] args) {
// 从连接池中获取一个连接
try (Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement("SELECT ENAME FROM EMP WHERE DEPTNO = ?")) {
pstmt.setInt(1, 10); // 查询 10 号部门的员工
try (ResultSet rs = pstmt.executeQuery()) {
System.out.println("10 号部门的员工:");
while (rs.next()) {
System.out.println(rs.getString("ENAME"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
// 注意:在应用程序关闭时,应该关闭连接池
// dataSource.close();
}
}
常见问题与解决方案
问题 1: java.sql.SQLException: No suitable driver found
- 原因:JDBC 驱动 JAR 文件没有添加到项目的类路径中。
- 解决方案:确保
ojdbc8.jar(或你下载的版本) 在你的构建路径中,如果你使用 IDE (如 IntelliJ IDEA, Eclipse),请检查库是否已正确添加,如果你使用 Maven/Gradle,确保依赖已下载并生效。
问题 2: java.sql.SQLException: Listener refused the connection with the following error: ORA-12505, TNS:no listener
- 原因:数据库 URL 中的端口号 (
1521) 或服务名 (ORCLCDB) 错误,数据库服务器可能没有运行,或者监听器没有配置为监听该服务名。 - 解决方案:
- 使用
tnsping命令测试监听是否正常:tnsping ORCLCDB。 - 使用 SQL*Plus 或 SQL Developer 尝试手动连接,验证用户名、密码、主机、端口和服务名是否全部正确。
- 使用
问题 3: java.sql.SQLException: Invalid username/password; logon denied
- 原因:提供的数据库用户名或密码错误。
- 解决方案:仔细检查用户名和密码,注意大小写。
问题 4: java.sql.SQLException: The Network Adapter could not establish the connection
- 原因:网络问题,Java 应用程序无法到达数据库服务器。
- 解决方案:
- 检查数据库服务器的 IP 地址是否正确。
- 检查防火墙是否阻止了
1521端口的通信。 - 确保数据库服务器正在运行。
| 技术点 | 关键点 |
|---|---|
| 驱动 | 使用 ojdbc8.jar (Java 8+),通过 Maven/Gradle 管理依赖。 |
| 连接 | 使用 DriverManager.getConnection(),URL 格式为 jdbc:oracle:thin@...。 |
| 核心对象 | Connection (连接), Statement/PreparedStatement (执行SQL), ResultSet (结果集)。 |
| 最佳实践 | 必须使用 try-with-resources 关闭资源;强烈推荐使用 PreparedStatement 防止注入并提升性能。 |
| 性能优化 | 必须使用连接池(如 HikariCP)来管理数据库连接,避免频繁创建和销毁连接。 |
| 错误处理 | 捕获 SQLException,并根据错误信息(如 ORA- 错误码)排查问题。 |
你就可以在 Java 应用中稳定、高效地与 Oracle 数据库进行交互了。
