核心概念
要连接 Oracle 数据库,Java 程序需要一个“桥梁”,这个桥梁就是 JDBC (Java Database Connectivity) 驱动程序,Oracle 提供了官方的 JDBC 驱动,你需要将其添加到你的项目中。

第一步:获取 Oracle JDBC 驱动
Oracle 11g 数据库通常使用 ojdbc6.jar (适用于 JDK 6, 7, 8) 或 ojdbc8.jar (适用于 JDK 8 及以上,但兼容 11g) 驱动。
如何获取?
-
Oracle 官方下载:
- 访问 Oracle 官方网站:Oracle Database Downloads
- 找到 "Previous Releases" 部分,选择 "Oracle Database 11g Release 2" (11.2.0.x)。
- 在下载页面中,你需要接受许可协议,然后找到 "ODBC/JDBC" 部分下载
ojdbc6.jar。 - 注意:你需要拥有一个免费的 Oracle 账号才能下载。
-
Maven 依赖 (推荐): 如果你使用 Maven 管理项目,这是最简单的方式,在
pom.xml文件中添加以下依赖:
(图片来源网络,侵删)<!-- 对于 JDK 8 及以下版本 --> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.4</version> <!-- 可以使用 11.2.0.x 的任意版本 --> </dependency> <!-- 对于 JDK 11 及以上版本,使用 ojdbc8,它也兼容 11g --> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.3.0.0</version> <!-- 使用较新的版本通常没问题 --> </dependency> -
Gradle 依赖: 如果你使用 Gradle,在
build.gradle文件中添加:// 对于 JDK 8 及以下版本 implementation 'com.oracle.database.jdbc:ojdbc6:11.2.0.4' // 对于 JDK 11 及以上版本 implementation 'com.oracle.database.jdbc:ojdbc8:19.3.0.0'
第二步:编写 Java 连接代码
以下是几种常见的连接方式,从简单到推荐。
基本连接示例 (硬编码不推荐)
这种方式最直接,但强烈不推荐用于生产环境,因为密码等敏感信息硬编码在代码中。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class OracleBasicJdbc {
// 数据库连接信息
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
// localhost: 如果数据库在本地
// 1521: Oracle 默认监听端口
// ORCL: 数据库服务名 (SID),你的可能是 XE, ORCLPDB1 等,需要根据实际情况修改
private static final String USER = "scott"; // 你的数据库用户名
private static final String PASS = "tiger"; // 你的数据库密码
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
// 1. 注册 JDBC 驱动 (对于较新版本的 JDBC 驱动,这步通常是可选的)
Class.forName("oracle.jdbc.driver.OracleDriver");
// 2. 打开连接
System.out.println("正在连接到 Oracle 数据库...");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("连接成功!");
// 3. 创建执行语句
stmt = conn.createStatement();
String sql = "SELECT * FROM emp WHERE ROWNUM <= 5"; // 查询 emp 表的前5条数据
ResultSet rs = stmt.executeQuery(sql);
// 4. 处理结果集
System.out.println("员工ID\t员工姓名");
while (rs.next()) {
// 通过列名获取,更具可读性
int id = rs.getInt("EMPNO");
String name = rs.getString("ENAME");
System.out.println(id + "\t" + name);
}
// 5. 关闭资源
rs.close();
stmt.close();
conn.close();
} catch (ClassNotFoundException e) {
System.err.println("找不到 Oracle JDBC 驱动类,请检查 ojdbc.jar 是否在 classpath 中。");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("数据库连接或查询出错!");
e.printStackTrace();
} finally {
// 确保在 finally 块中关闭资源,防止资源泄漏
try {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
}
}
使用 try-with-resources (推荐)
Java 7 引入了 try-with-resources 语句,它可以自动实现 AutoCloseable 接口的对象(如 Connection, Statement, ResultSet),无需在 finally 块中手动关闭,代码更简洁、安全。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class OracleJdbcWithTryWithResources {
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
private static final String USER = "scott";
private static final String PASS = "tiger";
public static void main(String[] args) {
// try-with-resources 会自动关闭 conn, stmt, rs
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM emp WHERE ROWNUM <= 5")) {
System.out.println("连接成功!");
System.out.println("员工ID\t员工姓名");
while (rs.next()) {
int id = rs.getInt("EMPNO");
String name = rs.getString("ENAME");
System.out.println(id + "\t" + name);
}
} catch (SQLException e) {
System.err.println("数据库操作出错!");
e.printStackTrace();
}
}
}
第三步:连接字符串详解
jdbc:oracle:thin:@<host>:<port>:<service_name> 是最常用的连接字符串格式。
jdbc:oracle:thin: 指定使用 JDBC 的 "thin" 驱动,这是一个纯 Java 的驱动,无需客户端库。@<host>: 数据库服务器的 IP 地址或主机名。localhost,168.1.100,db.example.com。<port>: 数据库监听的端口号,默认是1521。<service_name>: 这是 Oracle 数据库的标识。非常重要!- SID: 早期版本的 Oracle 使用 SID (System Identifier) 来标识实例,如
ORCL,XE。 - Service Name: Oracle 9i 及以后版本推荐使用 Service Name,它更灵活,可以指向一个或多个实例。
ORCLPDB1(在 CDB/PDB 架构中) 或ORCL。
- SID: 早期版本的 Oracle 使用 SID (System Identifier) 来标识实例,如
如何确认你的 Service Name 或 SID?
-
*使用 SQLPlus 连接**:
sqlplus / as sysdba
然后执行以下查询:
-- 查看所有服务名 SELECT name FROM v$services; -- 查看当前实例的 SID SELECT instance_name FROM v$instance;
-
查看
tnsnames.ora文件: 这个文件通常位于 Oracle 客户端安装目录的network/admin目录下,它定义了数据库的网络连接别名。
第四步:常见问题与解决方案
-
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver- 原因: JVM 的类路径中没有找到
ojdbc.jar文件。 - 解决方案:
- 如果你使用 IDE (如 IntelliJ IDEA, Eclipse), 确保将
ojdbc.jar文件添加到项目的 Libraries/Dependencies 中。 - 如果你使用命令行编译和运行,确保使用
-cp或-classpath选项指定 jar 文件的路径:java -cp ".:/path/to/ojdbc6.jar" OracleJdbcWithTryWithResources
- 如果你使用 IDE (如 IntelliJ IDEA, Eclipse), 确保将
- 原因: JVM 的类路径中没有找到
-
java.sql.SQLException: Io 异常: The Network Adapter could not establish the connection- 原因: 程序无法连接到指定的主机和端口。
- 解决方案:
- 检查主机和端口: 确认
DB_URL中的localhost和1521是否正确,如果数据库不在本机,请使用正确的 IP 地址。 - 检查 Oracle 监听器: 确保Oracle数据库的监听器正在运行,在数据库服务器上执行
lsnrctl status命令检查。 - 检查防火墙: 确保运行数据库的服务器的防火墙允许来自你应用服务器的
1521端口入站连接。
- 检查主机和端口: 确认
-
java.sql.SQLException: ORA-01017: invalid username/password; logon denied- 原因: 用户名或密码错误。
- 解决方案: 仔细核对代码中的
USER和PASS变量是否与数据库中的用户名和密码完全一致(注意大小写)。
-
java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1- 原因: 这通常是一个底层错误,可能由权限问题、表空间不足或数据库内部错误引起。
- 解决方案: 检查连接用户是否有足够的权限执行操作,查看数据库的 alert log 文件以获取更详细的错误信息。
第五步:最佳实践
-
使用连接池: 在任何生产环境中,绝对不要每次请求都创建一个新的数据库连接,创建和销毁连接是非常昂贵的操作,应该使用连接池来管理和复用连接。
-
推荐框架: HikariCP (目前性能最好的连接池), Apache DBCP2, C3P0。
-
示例 (使用 HikariCP):
<!-- 在 pom.xml 中添加 HikariCP 依赖 --> <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.ResultSet; import java.sql.Statement; public class OracleHikariCPExample { private static HikariDataSource dataSource; static { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:ORCL"); config.setUsername("scott"); config.setPassword("tiger"); config.setDriverClassName("oracle.jdbc.driver.OracleDriver"); // 连接池配置 config.setMaximumPoolSize(10); config.setMinimumIdle(5); config.setConnectionTimeout(30000); // 30 seconds dataSource = new HikariDataSource(config); } public static void main(String[] args) { try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM emp WHERE ROWNUM <= 5")) { // ... 执行查询 } catch (SQLException e) { e.printStackTrace(); } } }
-
-
配置外部化: 将数据库连接信息(URL, 用户名, 密码)存储在外部配置文件(如
config.properties)或环境变量中,而不是硬编码在代码里。 -
使用
PreparedStatement: 对于参数化查询,始终使用PreparedStatement而不是Statement,它可以防止 SQL 注入攻击,并且对于重复执行的查询性能更好。 -
处理异常和关闭资源: 始终使用
try-with-resources或在finally块中确保所有数据库资源(Connection,Statement,ResultSet)都被正确关闭,避免资源泄漏。
