连接字符串是 Java 应用程序与 Oracle 数据库建立连接时必需的一串参数,它告诉 JDBC 驱动程序如何连接到数据库,这个字符串的格式会根据你使用的 Oracle JDBC 驱动版本 和 连接方式 的不同而有所变化。
核心连接字符串格式
连接字符串的基本结构如下:
jdbc:oracle:driver_type:[username/password]@host:port:SID
或者对于服务名:
jdbc:oracle:driver_type:[username/password]@//host:port/service_name
参数详解:
jdbc:oracle: 协议头,表示使用 Oracle 的 JDBC 驱动。driver_type: 驱动类型,这是最重要的区分部分,取决于你使用的 Oracle JDBC 驱动版本。thin: 瘦驱动,纯 Java 实现,轻量级,是现在的主流和推荐方式,它通过 Java Socket 直接与数据库的监听器通信。oci: OCI (Oracle Call Interface) 驱动,需要本地库(如ocijdbcXX.jar和一个本地的 OCI 动态链接库),依赖于 Oracle 客户端安装,它性能更好,但配置复杂,不推荐用于跨平台或容器化部署。
[username/password]: 数据库的用户名和密码,这是可选的,你也可以不在连接字符串中提供,而是在DriverManager.getConnection()方法中单独传入。host: 数据库服务器的 IP 地址或主机名。port: 数据库监听器的端口号,默认是1521。SID: 系统标识符,数据库实例的唯一名称,这是 Oracle 8i 及之前版本的主要标识方式。service_name: 服务名,Oracle 9i 引入的概念,是更现代、更灵活的数据库标识方式,一个数据库实例可以有多个服务名,推荐使用这种方式。
不同驱动版本的连接字符串示例
我们根据不同的 Oracle JDBC 驱动版本来看具体的连接字符串写法。
使用 Oracle JDBC 驱动(ojdbcX.jar)
这是最传统的方式,需要手动下载 Oracle JDBC 驱动包(如 ojdbc8.jar, ojdbc10.jar, ojdbc11.jar 等)并将其加入项目的 classpath。
场景 1: 使用 SID (传统方式)
String url = "jdbc:oracle:thin:username/password@hostname:port:SID"; String urlExample = "jdbc:oracle:thin:scott/tiger@localhost:1521:ORCL";
scott/tiger: 用户名和密码。localhost: 数据库服务器地址。1521: 端口。ORCL: 数据库的 SID。
场景 2: 使用 Service Name (推荐方式)
这种方式更通用,尤其是在使用 RAC (Real Application Clusters) 或 PDB (Pluggable Database) 时。
String url = "jdbc:oracle:thin:username/password@//hostname:port/service_name"; String urlExample = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1";
- 注意 的存在,这是使用 Service Name 时的语法要求。
ORCLPDB1: 数据库的服务名。
使用 Oracle Universal Connection Pool (UCP) 和 JDBC 驱动
UCP 是 Oracle 官方推荐的高性能连接池实现,它的连接字符串基本与原生驱动相同,但通常会配合 DataSource 使用。
// UCP 连接字符串格式与原生驱动完全一样
String url = "jdbc:oracle:thin:username/password@//hostname:port/service_name";
// 使用 UCP 的示例代码片段
OracleDataSource ods = new OracleDataSource();
ods.setURL(url);
ods.setUser("username");
ods.setPassword("password");
ods.setConnectionPoolName("MyConnectionPool");
// ... 配置 UCP 连接池参数 ...
// ods.setMinPoolSize(5);
// ods.setMaxPoolSize(20);
try (Connection conn = ods.getConnection()) {
// 使用连接
} // 连接在 try-with-resources 中会自动归还到池中
使用 Oracle JDBC 驱动模块 (JDK 9+ 模块化)
从 Oracle JDBC 驱动 19c 版本开始,驱动被打包为 Java 模块(oracle.jdbc),可以在 JDK 9 及更高版本中使用,无需将 JAR 文件放入 classpath。
场景 1: 使用 Service Name (推荐)
String url = "jdbc:oracle:thin:username/password@//hostname:port/service_name";
String urlExample = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1";
// 加载驱动模块
// 在模块描述文件 module-info.java 中需要 requires oracle.jdbc;
// 或者通过命令行参数 --add-modules oracle.jdbc
Class.forName("oracle.jdbc.OracleDriver");
try (Connection conn = DriverManager.getConnection(url, "scott", "tiger")) {
// 使用连接
}
高级连接属性 (Advanced Properties)
你可以在连接字符串的末尾附加 或 分隔的属性,用于配置连接行为。
格式:
jdbc:oracle:thin:...?property1=value1&property2=value2
或
jdbc:oracle:thin:...:property1=value1:property2=value2 (较旧的方式,不推荐)
常用属性示例:
oracle.net.CONNECT_TIMEOUT: 建立连接的超时时间(毫秒)。String url = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1?oracle.net.CONNECT_TIMEOUT=5000";
oracle.jdbc.ReadTimeout: 读取数据的超时时间(毫秒)。String url = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1?oracle.jdbc.ReadTimeout=30000";
includeSynonyms=true: 查询时是否包含同义词。String url = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1?includeSynonyms=true";
restrictGetTables=true: 限制DatabaseMetaData.getTables()的返回结果,提高性能。String url = "jdbc:oracle:thin:scott/tiger@//localhost:1521/ORCLPDB1?restrictGetTables=true";
完整代码示例 (使用 ojdbc8.jar 和 Service Name)
这是一个使用 Maven 管理依赖的完整示例。
Maven 依赖 (pom.xml)
<dependencies>
<!-- Oracle JDBC 驱动 -->
<!-- 注意:请根据你的 Oracle 数据库版本选择合适的 ojdbcX.jar -->
<!-- Oracle 19c 可以使用 ojdbc10 或 ojdbc11 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
</dependencies>
Java 代码 (OracleJdbcExample.java)
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/ORCLPDB1";
private static final String USER = "scott";
private static final String PASS = "tiger";
public static void main(String[] args) {
// 1. 加载 JDBC 驱动 (对于较新版本的 JDBC 驱动,这步通常是可选的)
try {
Class.forName("oracle.jdbc.OracleDriver");
} catch (ClassNotFoundException e) {
System.err.println("找不到 Oracle JDBC 驱动类。");
e.printStackTrace();
return;
}
// 2. 建立连接
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")) {
// 3. 处理结果集
if (rs.next()) {
System.out.println("连接成功!数据库返回消息: " + rs.getString("message"));
}
} catch (SQLException e) {
System.err.println("数据库连接或查询失败。");
e.err.println("SQL State: " + e.getSQLState());
e.printStackTrace();
}
}
}
总结与最佳实践
-
驱动选择:
- 新项目: 强烈推荐使用 Oracle JDBC 驱动模块 (JDK 9+),避免 JAR 管理的麻烦。
- 传统项目 (JDK 8): 使用 ojdbcX.jar,
X对应你的数据库版本(如ojdbc8.jarfor 12c/19c,ojdbc10.jarfor 19c/21c)。 - 避免使用
oci驱动,除非有特殊性能要求且环境可控。
-
标识符选择:
- 始终优先使用
Service Name,而不是SID。Service Name是 Oracle 的未来方向,更灵活、更强大。
- 始终优先使用
-
连接池:
- 在任何生产环境中,绝对不要直接使用
DriverManager创建连接,务必使用连接池(如 UCP, HikariCP, Apache DBCP)来管理数据库连接,以提高性能和资源利用率。
- 在任何生产环境中,绝对不要直接使用
-
安全:
- 不要将硬编码的用户名和密码放在代码中,应使用配置文件(如
application.properties)、环境变量或专门的密钥管理服务来管理敏感信息。
- 不要将硬编码的用户名和密码放在代码中,应使用配置文件(如
