目录
- 准备工作
- 安装 Oracle 数据库
- 获取数据库连接信息
- 下载 Oracle JDBC 驱动
- 核心步骤
- 添加驱动到项目
- 编写 Java 连接代码
- 代码示例
- 使用 JDBC
ojdbc8.jar(推荐) - 使用 JDBC
ojdbc11.jar(面向未来) - 使用第三方连接池 (如 HikariCP)
- 使用 JDBC
- 最佳实践
- 使用
try-with-resources管理资源 - 使用连接池
- 使用
PreparedStatement防止 SQL 注入 - 处理异常
- 使用
- 常见问题与解决方案
准备工作
在开始编码之前,请确保你已经具备以下条件:

a. 安装 Oracle 数据库
你需要一个可访问的 Oracle 数据库实例,这可以是本地安装的 Oracle Database,也可以是远程服务器上的数据库,甚至是 Oracle Cloud 的免费版。
b. 获取数据库连接信息
你需要从你的 DBA(数据库管理员)或 Oracle Cloud 控制台获取以下关键信息:
- 主机名: 数据库服务器的地址 (
localhost或mydb.oracle.com)。 - 端口号: Oracle 数据库监听的端口 (默认是
1521)。 - 服务名: 数据库的全局数据库名称 (
ORCLCDB.localdomain或XEPDB1)。这是 Oracle 推荐的连接标识符。 - SID: 系统标识符,是较老的方式,如果你的 DBA 给了你 SID,你也可以使用它。
- 用户名: 用于连接数据库的用户名 (
scott,hr, 或你自己的用户)。 - 密码: 对应用户的密码。
c. 下载 Oracle JDBC 驱动
Java 通过 JDBC (Java Database Connectivity) 规范与数据库交互,Oracle 提供了实现此规范的驱动程序。
- 下载地址: Oracle JDBC 驱动下载页面
- 选择版本:
- ojdbc8.jar: 针对 Java 8 和更高版本,这是目前最常用、最稳定的版本,适用于大多数项目。
- ojdbc11.jar: 针对 Java 11 及更高版本,完全基于 Java 模块化系统 (JPMS),如果你正在使用 Java 11+,并且你的项目是模块化的,这是一个不错的选择。
下载完成后,你会得到一个 .jar 文件。

核心步骤
a. 添加驱动到项目
你需要将下载的 .jar 文件添加到你的 Java 项目的类路径中。
-
对于 Maven 项目 (推荐): 在你的
pom.xml文件中添加以下依赖,请根据你下载的版本选择一个。使用 ojdbc8:
<dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.3.0.0</version> <!-- 请使用你下载的版本号 --> </dependency>使用 ojdbc11:
(图片来源网络,侵删)<dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc11</artifactId> <version>21.5.0.0</version> <!-- 请使用你下载的版本号 --> </dependency> -
对于 Gradle 项目: 在你的
build.gradle文件中添加:// 使用 ojdbc8 implementation 'com.oracle.database.jdbc:ojdbc8:19.3.0.0' // 请使用你下载的版本号
// 使用 ojdbc11 implementation 'com.oracle.database.jdbc:ojdbc11:21.5.0.0' // 请使用你下载的版本号
-
对于手动管理的项目: 将
.jar文件复制到项目的lib目录下,并在你的 IDE (如 IntelliJ IDEA 或 Eclipse) 中将其添加到库/模块路径中。
b. 编写 Java 连接代码
连接 Oracle 数据库的基本流程是固定的:
- 加载 JDBC 驱动。
- 创建数据库连接。
- 创建
Statement或PreparedStatement对象。 - 执行 SQL 查询并处理结果。
- 关闭所有资源。
代码示例
示例 1: 使用 JDBC ojdbc8.jar (最常用)
这是最经典的连接方式,适用于 Java 8 及以上环境。
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:@//<hostname>:<port>/<service_name>";
private static final String USER = "<username>";
private static final String PASS = "<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 'Hello Oracle' as message FROM DUAL")) {
// 1. 加载驱动 (对于 ojdbc8.jar, 在 JDBC 4.0+ 中是可选的,但显式调用更清晰)
// Class.forName("oracle.jdbc.OracleDriver");
System.out.println("成功连接到 Oracle 数据库!");
// 2. 执行查询
while (rs.next()) {
// 通过列名获取数据
String message = rs.getString("message");
System.out.println("查询结果: " + message);
}
} catch (SQLException e) {
System.err.println("连接数据库失败!");
e.printStackTrace();
}
}
}
如何替换连接字符串:
- 将
<hostname>替换为你的数据库主机名或 IP 地址。 - 将
<port>替换为端口号 (通常是1521)。 - 将
<service_name>替换为你的数据库服务名。 - 格式:
jdbc:oracle:thin:@//<host>:<port>/<service_name>
连接字符串的几种形式:
- 使用服务名 (推荐):
jdbc:oracle:thin:@//localhost:1521/XEPDB1 - 使用 SID (旧式):
jdbc:oracle:thin:@localhost:1521:ORCL - 使用 TNS 名称 (需要配置
tnsnames.ora):jdbc:oracle:thin:@myOracleDB
示例 2: 使用 JDBC ojdbc11.jar (面向未来)
这个版本与 ojdbc8 的使用方式几乎完全相同,主要区别在于它支持 Java 模块化。
// 代码与 ojdbc8 示例完全一样 // 只需要确保你的项目使用的是 ojdbc11.jar 依赖 // 并且在 module-info.java (如果有的话) 中添加 requires "com.oracle.database.jdbc";
示例 3: 使用第三方连接池 (HikariCP - 强烈推荐)
在实际生产环境中,直接使用 DriverManager 创建连接是非常低效的,每个连接的建立和销毁都有很高的开销,连接池(如 HikariCP, C3P0, DBCP)可以预先创建一组数据库连接,应用程序需要时从池中获取,使用完毕后归还给池,从而大大提高性能。
添加 HikariCP 依赖 (Maven):
<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.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class OracleHikariExample {
// HikariCP 配置
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
// 基础连接信息
config.setJdbcUrl("jdbc:oracle:thin:@//<hostname>:<port>/<service_name>");
config.setUsername("<username>");
config.setPassword("<password>");
// 连接池优化配置 (推荐)
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.addDataSourceProperty("useLocalSessionState", "true");
config.addDataSourceProperty("rewriteBatchedStatements", "true");
config.addDataSourceProperty("cacheResultSetMetadata", "true");
config.addDataSourceProperty("cacheServerConfiguration", "true");
config.addDataSourceProperty("elideSetAutoCommits", "true");
config.addDataSourceProperty("maintainTimeStats", "false");
// 初始化连接池
ds = new HikariDataSource(config);
}
public static void main(String[] args) {
// 从连接池中获取一个连接
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 'Hello Oracle from HikariCP' as message FROM DUAL")) {
System.out.println("从 HikariCP 连接池成功获取连接!");
while (rs.next()) {
String message = rs.getString("message");
System.out.println("查询结果: " + message);
}
} catch (SQLException e) {
System.err.println("获取连接失败!");
e.printStackTrace();
}
}
}
最佳实践
-
使用
try-with-resources- 如上例所示,
Connection,Statement,ResultSet等都实现了AutoCloseable接口,使用try-with-resources可以确保这些资源在任何情况下(无论是否发生异常)都会被自动关闭,避免资源泄漏。
- 如上例所示,
-
使用连接池
- 永远不要在应用程序中频繁地创建和销毁数据库连接,对于任何中大型应用,使用 HikariCP 这样的高性能连接池是必须的。
-
使用
PreparedStatement- 当你的 SQL 语句包含参数时,务必使用
PreparedStatement,它不仅可以防止 SQL 注入攻击,而且数据库可以预编译 SQL 语句,提高执行效率。// 错误示例 (易受SQL注入) // String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"; // stmt = conn.createStatement(); // rs = stmt.executeQuery(sql);
// 正确示例 String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, username); // 第一个 ? 替换为 username pstmt.setString(2, password); // 第二个 ? 替换为 password rs = pstmt.executeQuery();
- 当你的 SQL 语句包含参数时,务必使用
-
处理异常
SQLException是检查型异常,你必须处理它,至少要打印堆栈跟踪信息以便调试,在生产环境中,应该记录日志。
常见问题与解决方案
Q1: java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver
- 原因: Java 虚拟机在类路径中找不到
OracleDriver类。 - 解决方案: 确保
ojdbc8.jar(或ojdbc11.jar) 文件已经正确添加到项目的类路径中,对于 Maven/Gradle 项目,检查pom.xml或build.gradle文件,确保依赖已正确下载。
Q2: IO Error: The Network Adapter could not establish the connection
- 原因: 这是最常见的网络连接问题。
- Oracle 数据库服务未启动。
- 防火墙阻止了到
<hostname>:<port>的连接。 <hostname>或<port>错误。- 数据库监听器未配置或未正确监听该端口。
- 解决方案:
- 使用
tnsping <service_name>命令测试 TNS 名称解析是否成功。 - 使用
telnet <hostname> <port>命令测试网络是否可达,如果失败,说明是网络或防火墙问题。 - 登录到数据库服务器,检查监听器状态:
lsnrctl status。
- 使用
Q3: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
- 原因: 客户端提供的
service_name(或SID) 在数据库监听器中不存在或未注册。 - 解决方案:
- 确认你使用的服务名或 SID 是否正确。
- 在数据库服务器上,查询动态性能视图
v$service_names或v$instance确认正确的名称。 - 重启数据库或监听器以确保服务正确注册。
Q4: ORA-01017: invalid username/password; logon denied
- 原因: 用户名或密码错误。
- 解决方案: 仔细检查用户名和密码,注意大小写敏感问题,尝试在 SQL*Plus 或类似工具中直接登录以验证凭据。
