首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Java JDBC 連接 Oracle 常見異常與解決方案實戰

     編輯:Oracle 資料庫基礎

JDBC 連接 Oracle 典型異常排查指南

Java 應用通過 JDBC 訪問 Oracle 時,常遭遇連接緩慢、資料截斷、字符集亂碼等問題。本文針對三大高頻異常場景,提供經實戰驗證的解決方案與代碼最佳實踐。

場景一:連接極慢且拋出 ORA-00600 [ttcgcshnd-1]

現象:建立連接耗時極長,執行 SELECT 時拋出內部錯誤:

java.sql.SQLException: ORA-00600: internal error code, arguments: [ttcgcshnd-1], [0], [], [], [], [], [], []

根因:JDBC 驅動版本與資料庫版本不匹配,或使用了舊版 `classes12.jar`。

解決:

  • 使用 Oracle 安裝目錄下 `jdbc/lib/ojdbc8.jar` (11g+) 或 `ojdbc10.jar` (19c+)
  • 確保驅動版本與資料庫版本對應(參考 Oracle MOS Doc ID 393131.1)
  • 若使用連接池,檢查 `oracle.net.CONNECT_TIMEOUT` 設置

場景二:PreparedStatement setString 觸發「資料大小超出最大值」

現象:向 `VARCHAR2(3000)` 欄位寫入長字符串時拋出:

java.sql.SQLException: Data size bigger than max size for this type: 3000

根因:`setString` 受限於 JDBC 實現的緩衝區大小,大字符串需使用流式寫入。

解決:改用 `setCharacterStream`

String sql = "INSERT INTO test(name, addr) VALUES (?, ?)";
try (PreparedStatement pst = conn.prepareStatement(sql)) {
    pst.setString(1, "kingfish");
    
    // 建立字符流,避免 32767 字節限制
    char[] carray = new char[1000];
    Arrays.fill(carray, '我');
    String longStr = new String(carray);
    
    try (Reader reader = new StringReader(longStr)) {
        pst.setCharacterStream(2, reader, longStr.length());
        pst.executeUpdate();
    }
}

關鍵點:

  • `setCharacterStream` 接受 `Reader` 物件,支援超大文本
  • 第三參數為字符長度,非位元組長度
  • 配合 `try-with-resources` 確保流關閉

場景三:字符集亂碼 (NLS_LANG 不匹配)

現象:中文存入資料庫變亂碼,或讀出顯示 `???`。

排查清單:

  1. 資料庫字符集:`SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET';`
  2. 客戶端環境變數 `NLS_LANG`(Windows 註冊表 / Linux `export NLS_LANG=AMERICAN_AMERICA.AL32UTF8`)
  3. JDBC URL 不需額外字符集參數,驅動自動協商

最佳實踐:統一使用 `AL32UTF8` (資料庫) + `UTF-8` (JVM `file.encoding`),避免 `ZHS16GBK` 等舊字符集。

完整測試代碼結構

public class OracleJdbcTest {
    private static final String URL = "jdbc:oracle:thin:@localhost:1521:oradb";
    private static final String USER = "system";
    private static final String PWD = "manager";

    public static void main(String[] args) {
        testLargeTextInsert();
    }

    static void testLargeTextInsert() {
        // ... 實現上述邏輯
    }
}

避坑提示

  • 不要混用 `ojdbc6/7/8/10`,根據 JDK 版本選擇
  • 大文本優先用 `setCharacterStream` / `setClob`
  • 連接池建議使用 HikariCP,配置 `connectionInitSql` 驗證有效性
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved