首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java JDBC 連接 Oracle 與 SQL Server 完整指南:驅動、URL、連接池與最佳實踐

     編輯:Java 相關知識

前言

JDBC 是 Java 訪問關係數據庫的標準 API。本文詳細講解連接 Oracle 與 SQL Server 的驅動依賴、JDBC URL 格式、連接參數、連接池配置 (HikariCP)、事務控制、預編譯語句防注入、結果集處理等全鏈路實戰要點。

驅動依賴 (Maven)

<!-- Oracle 19c/21c -->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc11</artifactId>
    <version>23.4.0.0</version>
</dependency>

<!-- SQL Server (Microsoft 官方驅動) -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>12.4.2.jre11</version>
</dependency>

<!-- 連接池 HikariCP (高性能首選) -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>5.0.1</version>
</dependency>

JDBC URL 格式詳解

數據庫URL 模板關鍵參數
Oracle (Thin)jdbc:oracle:thin:@//host:port/service_name服務名優於 SID;支援 TNS 別名
Oracle (TNS)jdbc:oracle:thin:@(description=(address=(host=...)(port=...))(connect_data=(service_name=...)))無需 tnsnames.ora
SQL Serverjdbc:sqlserver://host:port;databaseName=xxx;encrypt=true;trustServerCertificate=trueencrypt=true 開啟 TLS;trustServerCertificate=true 跳過憑證驗證 (開發環境)
SQL Server (Named Instance)jdbc:sqlserver://host;instanceName=INST1;databaseName=xxx動態端口由 SQL Browser 解析

連接池配置 (HikariCP)

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:oracle:thin:@//192.168.1.100:1521/ORCL");
config.setUsername("app_user");
config.setPassword("secret");
// 核心池大小 = CPU核心數 * 2 + 1 (經驗值)
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000); // 30s 獲取連接超時
config.setIdleTimeout(600000);      // 10min 空閒回收
config.setMaxLifetime(1800000);     // 30min 最大存活
config.setConnectionTestQuery("SELECT 1 FROM DUAL"); // Oracle 驗證語句
config.setPoolName("OraclePool");

HikariDataSource ds = new HikariDataSource(config);

// 使用
try (Connection conn = ds.getConnection()) {
    // 業務邏輯
} // 自動歸還連接池

核心操作模板

1. 預編譯語句 (PreparedStatement) - 防 SQL 注入

String sql = "SELECT id, username, email FROM users WHERE status = ? AND create_time > ?";
try (Connection conn = ds.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql)) {
    ps.setInt(1, 1);
    ps.setTimestamp(2, Timestamp.valueOf("2024-01-01 00:00:00"));
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.println(rs.getLong("id") + " | " + rs.getString("username"));
        }
    }
}

2. 事務控制

Connection conn = ds.getConnection();
try {
    conn.setAutoCommit(false);
    // 多條 DML
    try (PreparedStatement ps1 = conn.prepareStatement("UPDATE account SET balance = balance - ? WHERE id = ?");
         PreparedStatement ps2 = conn.prepareStatement("UPDATE account SET balance = balance + ? WHERE id = ?")) {
        ps1.setBigDecimal(1, new BigDecimal("100.00")); ps1.setLong(2, 1L); ps1.executeUpdate();
        ps2.setBigDecimal(1, new BigDecimal("100.00")); ps2.setLong(2, 2L); ps2.executeUpdate();
    }
    conn.commit();
} catch (Exception e) {
    conn.rollback();
    throw e;
} finally {
    conn.setAutoCommit(true);
    conn.close();
}

3. 批量操作

String sql = "INSERT INTO log (msg, level) VALUES (?, ?)";
try (Connection conn = ds.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql)) {
    conn.setAutoCommit(false);
    for (int i = 0; i < 10000; i++) {
        ps.setString(1, "log message " + i);
        ps.setString(2, "INFO");
        ps.addBatch();
        if (i % 1000 == 0) ps.executeBatch(); // 分批提交
    }
    ps.executeBatch();
    conn.commit();
}

數據類型映射表

Java 類型OracleSQL Serverset/get 方法
StringVARCHAR2 / NVARCHAR2NVARCHAR / VARCHARsetString / getString
Long / longNUMBER(19)BIGINTsetLong / getLong
BigDecimalNUMBER(p,s)DECIMAL(p,s)setBigDecimal / getBigDecimal
java.sql.DateDATE (無時間)DATEsetDate / getDate
java.sql.TimestampTIMESTAMP / DATEDATETIME / DATETIME2setTimestamp / getTimestamp
byte[]BLOB / RAWVARBINARY / IMAGEsetBytes / getBytes
Clob / BlobCLOB / BLOBVARCHAR(MAX) / VARBINARY(MAX)setClob/setBlob / getClob/getBlob

常見坑點與解決

  1. Oracle 時區不一致:JVM -Duser.timezone=GMT+8 或連接屬性 oracle.jdbc.timezoneAsRegion=false。
  2. SQL Server 加密連接失敗:JDK 11+ 默認要求有效憑證,開發期加 trustServerCertificate=true;生產需導入 CA 憑證。
  3. 游標泄漏:ResultSet/Statement/Connection 必須在 finally 或 try-with-resources 中關閉。
  4. 大字段讀取:CLOB/BLOB 需流式讀取,避免 getString() 一次性載入內存。
  5. 連接池洩漏:啟用 config.setLeakDetectionThreshold(30000) 檢測長時間未歸還連接。

總結

JDBC 雖屬底層 API,但掌握「驅動選型 → URL 參數 → 連接池調優 → 預編譯防注入 → 事務邊界 → 資源關閉」六步曲,即可構建高性能、安全穩定的數據訪問層。建議新項目直接使用 Spring Data JPA / MyBatis 等 ORM 框架封裝 JDBC 細節,專注業務建模;遇到複雜報表、批量導入等場景再直接操作 JDBC 發揮極致性能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved