核心原理
Java 通过 JDBC (Java Database Connectivity) API 来与数据库进行交互,JDBC 是一套标准的 Java API,定义了如何连接数据库、执行 SQL 语句、处理结果等。

整个过程可以概括为以下几个步骤:
- 加载驱动:让 JVM 知道使用哪个数据库的驱动程序。
- 获取连接:使用数据库的 URL、用户名和密码,与数据库建立一个网络连接。
- 创建语句:通过连接对象,创建一个
Statement或PreparedStatement对象,用于执行 SQL。 - 执行 SQL:使用语句对象执行 SQL 查询或更新。
- 处理结果:如果是查询,会得到一个
ResultSet对象,遍历这个对象来获取数据。 - 关闭资源:按照“后开先关”的原则,依次关闭
ResultSet、Statement和Connection,释放数据库资源。
准备工作
在开始编码之前,你需要准备两样东西:
1 Oracle JDBC 驱动
你需要下载 Oracle 的 JDBC 驱动 JAR 包,目前最常用的是 ojdbc8.jar (适用于 JDK 8) 或 ojdbc11.jar (适用于 JDK 11 及以上)。
- 下载地址:你可以从 Oracle 官网或 Maven 中央仓库获取。
- Oracle 官方下载页面 (需要登录)
- Maven 中央仓库 (推荐使用 Maven/Gradle 管理依赖,见下文)
2 数据库连接信息
你需要从你的 DBA 或系统管理员那里获取以下信息:

- 主机名:数据库服务器的 IP 地址或域名。
- 端口号:Oracle 监听器监听的端口,默认是
1521。 - 服务名/SID:标识你要连接的具体数据库实例,Oracle 10g 及以后版本推荐使用 服务名。
- 用户名:连接数据库的用户名。
- 密码:连接数据库的密码。
实现方式
有三种主流的方式来实现 Java 连接 Oracle 数据库:
手动下载 JAR 包 (传统方式)
这是最直接的方式,适合小型项目或快速验证。
-
下载并添加 JAR 包:将下载的
ojdbc8.jar文件添加到你的项目类路径 中。- 在 IDE (如 IntelliJ IDEA/Eclipse) 中:右键项目 -> Build Path / Project Structure -> Libraries -> Add External JARs...,然后选择你的
ojdbc8.jar文件。 - 使用命令行编译运行:需要用
-cp或-classpath参数指定 JAR 包路径。# 编译 javac -cp ".;ojdbc8.jar" YourJavaFile.java # 运行 java -cp ".;ojdbc8.jar" YourJavaFile
(注意:Windows 使用 分隔路径,Linux/macOS 使用 )
(图片来源网络,侵删)
- 在 IDE (如 IntelliJ IDEA/Eclipse) 中:右键项目 -> Build Path / Project Structure -> Libraries -> Add External JARs...,然后选择你的
-
编写 Java 代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class OracleJdbcDemo {
// 数据库连接信息
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) {
// 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")) {
// 1. 加载驱动 (对于新版本的驱动,这一步通常是可选的,但写上更规范)
Class.forName("oracle.jdbc.OracleDriver");
System.out.println("成功连接到 Oracle 数据库!");
// 2. 执行查询并处理结果
while (rs.next()) {
// 通过列名获取数据
String message = rs.getString("message");
System.out.println("查询结果: " + message);
}
} catch (ClassNotFoundException e) {
System.err.println("Oracle JDBC 驱动未找到!");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("数据库连接或查询失败!");
e.printStackTrace();
}
}
}
使用 Maven/Gradle (推荐方式)
在现代 Java 项目中,强烈推荐使用 Maven 或 Gradle 来管理项目依赖,这样你无需手动下载和添加 JAR 包。
- 配置 Maven (
pom.xml)
在 pom.xml 文件中添加 oracle-java-sdk 依赖,推荐使用较新的版本。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>oracle-jdbc-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Oracle JDBC 驱动依赖 -->
<!-- 注意:groupId 和 artifactId 可能有变化,请查找最新的 -->
<!-- 对于 ojdbc8, groupId 通常是 com.oracle.database.jdbc -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
</dependencies>
</project>
- 编写 Java 代码
代码与方式一基本相同,Maven 会自动处理类路径,你无需手动加载驱动(Class.forName 在新驱动中通常可以省略,但保留也无妨)。
// 代码同上,但无需手动添加 JAR 包到项目
import java.sql.*;
public class OracleMavenDemo {
// ... (DB_URL, USER, PASS 定义同上)
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT SYSDATE as current_date FROM DUAL")) {
System.out.println("成功连接到 Oracle 数据库!");
if (rs.next()) {
Date currentDate = rs.getDate("current_date");
System.out.println("Oracle 服务器当前时间: " + currentDate);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
使用连接池 (生产环境最佳实践)
在真实的应用中,频繁地创建和销毁数据库连接是非常消耗资源的。连接池 应运而生,它预先创建一组数据库连接,并将它们放入池中,当需要连接时,从池中获取;使用完毕后,将连接归还到池中,而不是关闭。
HikariCP 是目前性能最好的连接池实现之一。
- 配置 Maven (
pom.xml)
你需要添加 HikariCP 和 Oracle JDBC 驱动的依赖。
<!-- pom.xml -->
<dependencies>
<!-- Oracle JDBC 驱动 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
<!-- HikariCP 连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
</dependencies>
- 编写 Java 代码
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 OracleHikariCPDemo {
public static void main(String[] args) {
// 1. 配置 HikariCP
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.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.setMaximumPoolSize(10); // 最大连接数
// 2. 创建数据源
try (HikariDataSource ds = new HikariDataSource(config)) {
System.out.println("HikariCP 连接池创建成功!");
// 3. 从连接池获取连接
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 'Connection from HikariCP!' as message FROM DUAL")) {
System.out.println("成功从连接池获取连接并执行查询!");
if (rs.next()) {
System.out.println("查询结果: " + rs.getString("message"));
}
} // 连接在这里被自动归还到连接池
} catch (SQLException e) {
System.err.println("获取连接或查询失败!");
e.printStackTrace();
} // 数据源在这里被关闭
}
}
常见问题与最佳实践
1 URL 格式
Oracle 的 JDBC URL 有几种格式,推荐使用第一种(服务名格式)。
-
格式一 (推荐 - 服务名)
jdbc:oracle:thin:@//<host>:<port>/<service_name>thin:表示使用纯 Java 实现的瘦客户端驱动。//host:port:主机和端口。/service_name:服务名。
-
格式二 (SID)
jdbc:oracle:thin:@<host>:<port>:<sid>这种格式在较老的 Oracle 版本中更常见。
-
格式三 (TNS)
jdbc:oracle:thin:@<TNS_name>TNS_name是一个在tnsnames.ora文件中定义的网络服务名,这种方式需要配置客户端环境,不常用。
2 Class.forName() 还需要吗?
对于 ojdbc8.jar 及更高版本的驱动,不再需要 Class.forName("oracle.jdbc.OracleDriver"),这是因为驱动 JAR 中的 META-INF/services/java.sql.Driver 文件会自动向 JDBC 驱动管理器注册驱动,保留它不会造成 harm,并且可以增加代码的向后兼容性。
3 字符集问题
如果应用程序和数据库使用的字符集不一致,可能会导致乱码(中文显示为 或乱码)。
- 解决方案:在 JDBC URL 中指定客户端字符集。
String DB_URL = "jdbc:oracle:thin:@//your_host:your_port/your_service_name?useUnicode=true&characterEncoding=UTF-8"; // 对于 Oracle,更常用的是 String DB_URL = "jdbc:oracle:thin:@//your_host:your_port/your_service_name?useFetchSize=50&useServerPrepStmts=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8";
确保数据库服务端的
NLS_LANG环境变量也设置为正确的字符集(如AMERICAN_AMERICA.AL32UTF8)。
4 资源关闭
数据库连接(Connection)、语句(Statement)和结果集(ResultSet)都是非常宝贵的系统资源。必须在使用后关闭它们,否则会导致连接泄漏,最终使数据库无连接可用。
- 传统方式:在
finally块中关闭,并确保关闭前不为null。 - 现代方式 (推荐):使用 try-with-resources 语句,如上面的所有示例所示,它能确保实现了
AutoCloseable接口的对象在语句块结束时被自动关闭,代码更简洁、安全。
5 SQL 注入
永远不要使用字符串拼接来构建 SQL 语句,这极易受到 SQL 注入攻击。
-
危险做法:
String sql = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
-
安全做法:使用
PreparedStatement。String sql = "SELECT * FROM users WHERE username = ? AND password = ?"; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); // ... 执行查询 }
| 场景 | 推荐方式 | 优点 | 缺点 |
|---|---|---|---|
| 学习/快速测试 | 手动下载 JAR 包 | 简单直接,无需构建工具 | 依赖管理麻烦,容易版本冲突 |
| 标准 Java 项目 | Maven/Gradle | 依赖管理自动化,版本清晰,可复用 | 需要学习构建工具 |
| 生产环境应用 | Maven/Gradle + 连接池 | 高性能、高可用、资源复用、稳定可靠 | 配置相对复杂 |
对于任何严肃的项目,都强烈建议使用 Maven/Gradle 管理依赖,并结合 HikariCP 这样的连接池 来构建健壮的数据库访问层。
