环境准备
在编写代码之前,请确保您已经准备好了以下环境:
- Java 开发环境 (JDK): 确保您的系统已安装 JDK (JDK 8 或更高版本),并配置好
JAVA_HOME环境变量。 - Oracle 数据库: 确保您有一个正在运行的 Oracle 数据库实例,并且知道以下连接信息:
- 主机名/IP地址: 数据库服务器的地址。
- 端口号: Oracle 数据库的监听端口,默认是
1521。 - 服务名/SID: 这是数据库的唯一标识符,服务名是现代 Oracle 数据库推荐的方式。
- 用户名: 数据库的用户名。
- 密码: 对应的密码。
- Oracle JDBC 驱动: Java 通过 JDBC (Java Database Connectivity) 协议连接数据库,您需要下载 Oracle 提供的 JDBC 驱动 JAR 文件。
如何获取 JDBC 驱动?
您可以从 Oracle 官方网站下载驱动,驱动通常分为两种类型:
- ojdbc8.jar: 用于 JDK 8。
- ojdbc11.jar: 用于 JDK 11 及更高版本。
下载地址: Oracle JDBC 驱动下载页面
下载后,请将 JAR 文件添加到您的 Java 项目的类路径中,如果您使用 Maven 或 Gradle,可以直接添加依赖。
使用 Maven/Gradle 添加依赖 (推荐)
手动管理 JAR 文件很麻烦,使用构建工具是更好的选择。
Maven (pom.xml)
根据您的 JDK 版本,在 pom.xml 中添加相应的依赖。
对于 JDK 8:
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version> <!-- 请使用您下载的版本号 -->
</dependency>
对于 JDK 11+:
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>21.5.0.0</version> <!-- 请使用您下载的版本号 -->
</dependency>
Gradle (build.gradle)
对于 JDK 8:
implementation 'com.oracle.database.jdbc:ojdbc8:19.3.0.0' // 请使用您下载的版本号
对于 JDK 11+:
implementation 'com.oracle.database.jdbc:ojdbc11:21.5.0.0' // 请使用您下载的版本号
Java 连接代码示例
以下是几个不同场景下的代码示例,从最基础到最佳实践。
示例 1:基础连接与查询 (不推荐用于生产)
这个示例展示了最基本的连接、查询和关闭资源的流程。注意: 这种方式在发生异常时可能会导致资源(如 Connection)没有被正确关闭。
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:@//your_host:your_port/your_service_name";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void main(String[] args) {
// 1. 加载 JDBC 驱动 (对于较新版本的JDK,这步通常可以省略)
try {
Class.forName("oracle.jdbc.OracleDriver");
} catch (ClassNotFoundException e) {
System.out.println("找不到 Oracle JDBC Driver");
e.printStackTrace();
return;
}
// try-with-resources 语句确保资源自动关闭
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 'Hello from Oracle!' as message FROM dual")) {
if (conn != null) {
System.out.println("成功连接到 Oracle 数据库!");
}
// 处理结果集
while (rs.next()) {
// 通过列名获取数据,更安全
String message = rs.getString("message");
System.out.println("查询结果: " + message);
}
} catch (SQLException e) {
System.out.println("数据库连接或查询失败!");
e.printStackTrace();
}
}
}
示例 2:使用 try-with-resources 的最佳实践 (推荐)
这是现代 Java (7+) 推荐的方式。try-with-resources 语句可以确保实现了 AutoCloseable 接口(如 Connection, Statement, ResultSet)的资源在代码块执行完毕后自动关闭,即使在发生异常时也能保证资源被释放。
上面的示例 1 已经使用了 try-with-resources,这是一个非常好的实践。
示例 3:使用 PreparedStatement 防止 SQL 注入
当您的 SQL 语句包含用户输入时,永远不要使用字符串拼接来构建 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:@//your_host:your_port/your_service_name";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void findEmployeeById(int employeeId) {
String sql = "SELECT employee_id, first_name, last_name FROM employees WHERE employee_id = ?";
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 设置参数 (索引从1开始)
pstmt.setInt(1, employeeId);
try (ResultSet rs = pstmt.executeQuery()) {
System.out.println("正在查找 ID 为 " + employeeId + " 的员工...");
if (rs.next()) {
int id = rs.getInt("employee_id");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
System.out.println("找到员工: ID=" + id + ", 姓名=" + firstName + " " + lastName);
} else {
System.out.println("未找到 ID 为 " + employeeId + " 的员工。");
}
}
} catch (SQLException e) {
System.out.println("查询员工时出错!");
e.printStackTrace();
}
}
public static void main(String[] args) {
// 示例:查询ID为101的员工
findEmployeeById(101);
}
}
示例 4:使用连接池 (生产环境必备)
在真实的应用中,创建和销毁数据库连接是非常消耗资源的,我们使用连接池来复用连接,提高性能。HikariCP 是目前性能最好的连接池之一。
添加 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.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class OracleWithHikariCP {
// 初始化连接池 (通常在应用启动时执行一次)
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:oracle:thin:@//your_host:your_port/your_service_name");
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 'Hello from HikariCP!' as message FROM dual");
ResultSet rs = pstmt.executeQuery()) {
System.out.println("从连接池成功获取连接!");
if (rs.next()) {
System.out.println("查询结果: " + rs.getString("message"));
}
} catch (SQLException e) {
System.out.println("获取连接或查询失败!");
e.printStackTrace();
}
// 在应用关闭时,关闭连接池
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
System.out.println("连接池已关闭。");
}
}
}
连接 URL 格式说明
jdbc:oracle:thin: 是连接协议。
- thin: 表示使用纯 Java 的瘦客户端驱动,无需在客户端安装 Oracle 软件。
- oci: 表示使用 Oracle Call Interface,需要安装 Oracle 客户端,性能更好,但配置更复杂,在 Java Web 应用中通常使用
thin。
URL 格式:
-
主机名 + 端口 + 服务名 (推荐)
jdbc:oracle:thin:@//<host>:<port>/<service_name>示例:
jdbc:oracle:thin:@//localhost:1521/XE -
主机名 + 端口 + SID (旧版)
jdbc:oracle:thin:@<host>:<port>:<SID>示例:
jdbc:oracle:thin:@localhost:1521:XE -
TNS 名称 (使用 tnsnames.ora 文件) 如果您在客户端配置了
tnsnames.ora文件,可以使用别名。jdbc:oracle:thin:@<TNS_alias>示例:
jdbc:oracle:thin:@my_oracle_db
常见问题与解决方案
-
java.lang.ClassNotFoundException: oracle.jdbc.OracleDriver- 原因: JDBC 驱动 JAR 文件没有被添加到项目的类路径中。
- 解决: 确保
ojdbcX.jar在CLASSPATH环境变量中,或者已正确添加到您的 IDE (如 IntelliJ IDEA, Eclipse) 或 Maven/Gradle 项目中。
-
java.sql.SQLException: Invalid Oracle URL specified- 原因: 数据库连接 URL 的格式不正确。
- 解决: 仔细检查您的 URL,确保主机名、端口和服务名/SID 都正确无误,格式应为
jdbc:oracle:thin:@//host:port/service_name。
-
java.sql.SQLException: IO Error: The Network Adapter could not establish the connection- 原因: 无法连接到数据库服务器,最常见的原因:
- Oracle 数据库服务未启动。
- 防火墙阻止了
1521(或其他) 端口。 - 主机名或 IP 地址错误。
- 端口号错误。
- 解决: 检查数据库状态、防火墙设置和网络连接,可以使用
tnsping your_service_name命令来测试网络连接。
- 原因: 无法连接到数据库服务器,最常见的原因:
-
java.sql.SQLException: ORA-01017: invalid username/password; logon denied- 原因: 用户名或密码错误。
- 解决: 核对您输入的用户名和密码是否完全正确,注意大小写。
-
java.sql.SQLException: ORA-12514: TNS:listener does not currently know of service requested in connect descriptor- 原因: 您在 URL 中提供的服务名 (
service_name) 在 Oracle 监听器中不存在。 - 解决: 登录到 Oracle 服务器,使用
lsnrctl services命令查看监听器正在提供哪些服务名,并确保您的 URL 中使用的是正确的服务名。
- 原因: 您在 URL 中提供的服务名 (
希望这份详细的指南能帮助您成功地在 Java 中连接 Oracle 数据库!
