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

Java + Oracle 開發實戰:JDBC 驅動、大對象與可捲動結果集避坑指南

     編輯:Java 相關知識

問題一:JDBC 驅動載入的三種姿勢

  1. Class.forName():最常見,觸發靜態區塊向 DriverManager 註冊驅動。但 Microsoft JVM (IE Applet) 無法正確初始化,慎用。
  2. 系統屬性檔:jdbc.drivers=oracle.jdbc.driver.OracleDriver,支援多驅動、不改代碼切換資料庫,彈性最佳。
  3. DriverManager.registerDriver():直接註冊,最可靠,任何環境(含 Applet)均適用,但靈活性稍遜。

建議:生產環境優先考慮屬性檔或 registerDriver,避免 Class.forName 在特定容器失效。

問題二:大對象(BLOB/CLOB)存儲的正確打開方式

網上 99% 教程(含 Sun 早期文檔)對 Oracle BLOB 處理有誤導。關鍵點:

  • 標準 JDBC 2.0 不支援直接 setBinaryStream 寫入 BLOB,會拋 IO 異常而非 SQL 異常。
  • 變通方案 A:用 LONG RAW 欄位,配合 PreparedStatement.setBinaryStream() 直接寫入。
  • 正統方案 B:用 Oracle 專有 API 操作 BLOB:
// 1. 插入空 BLOB
conn.setAutoCommit(false);
stmt.executeUpdate("INSERT INTO tb_file VALUES ('aaa.gif', empty_blob())");

// 2. 查詢 FOR UPDATE 鎖定該行,取得 BLOB 定位器
ResultSet rs = stmt.executeQuery(
    "SELECT detail FROM tb_file WHERE name='aaa.gif' FOR UPDATE");
if (rs.next()) {
    oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob(1);
    OutputStream out = blob.getBinaryOutputStream();
    // 3. 分塊寫入
    byte[] buf = new byte[blob.getBufferSize()];
    InputStream in = new FileInputStream(file);
    int len;
    while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
    in.close(); out.close();
    conn.commit();
}

讀取同理:blob.getBinaryStream() 而非 rs.getBinaryStream()。核心原則:BLOB 操作必須在同一事務中先 SELECT FOR UPDATE 取得定位器,再讀寫。

問題三:可捲動結果集的記憶體陷阱

Oracle 明確不支援伺服器端游標捲動。JDBC 驅動提供的 TYPE_SCROLL_INSENSITIVE 實際是將全部結果集緩存在客戶端記憶體。小資料量無感,大資料量直接 OOM。鐵律:大量資料查詢寧用笨辦法(分頁 SQL、游標迴圈),勿用可捲動結果集。

總結速查表

場景推薦做法避坑關鍵
驅動載入屬性檔 / registerDriverApplet 環境禁用 Class.forName
二進制大檔LONG RAW + setBinaryStream標準 JDBC 不支援直寫 BLOB
BLOB 正統用法empty_blob() + FOR UPDATE + 專有 API同一事務、先 SELECT 再寫入
海量查詢分頁 SQL / 伺服器端游標禁用 TYPE_SCROLL_* 防 OOM
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved