首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

Java 開發 Oracle 核心技術避坑指南:JDBC 載入、BLOB 存儲、可捲動結果集

     編輯:Oracle 資料庫相關知識

一、JDBC 驅動載入三種方式

方式代碼優缺點
Class.forNameClass.forName("oracle.jdbc.driver.OracleDriver")簡單,但 MS JVM (IE Applet) 無法正確初始化靜態區塊
系統屬性檔System.getProperty().load(...); jdbc.drivers=oracle.jdbc.driver.OracleDriver可同時載入多驅動,切換 DB 無需改代碼
DriverManager.registerDriverDriverManager.registerDriver(new OracleDriver())最可靠,任何環境(含 Applet)均可用

建議:生產環境採用方式 3 或 2+3 結合。

二、BLOB 二進制檔案存儲:標準 JDBC 做不到,需 Oracle 擴充 API

錯誤做法

// 標準 JDBC 2.0 不支援直接 setBinaryStream 寫 BLOB
ps.setBinaryStream(1, fin, len); // 拋出 IO 異常而非 SQL 異常

正確做法:Oracle 專有 API

// 1. 建表
CREATE TABLE tb_file(name VARCHAR2(20), detail BLOB);

// 2. 插入空 BLOB 取得 Locator
conn.setAutoCommit(false);
stmt.executeUpdate("INSERT INTO tb_file VALUES ('aaa.gif', EMPTY_BLOB())");

// 3. SELECT FOR UPDATE 取得 BLOB 物件
ResultSet rs = stmt.executeQuery("SELECT detail FROM tb_file WHERE name='aaa.gif' FOR UPDATE");
if (rs.next()) {
  BLOB blob = ((OracleResultSet)rs).getBLOB(1);
  OutputStream out = ((oracle.sql.BLOB)blob).getBinaryOutputStream();
  byte[] buf = new byte[((oracle.sql.BLOB)blob).getBufferSize()];
  InputStream fin = new FileInputStream(file);
  int len;
  while ((len = fin.read(buf)) != -1) out.write(buf, 0, len);
  fin.close(); out.close();
  conn.commit();
}

讀取 BLOB

BLOB blob = ((OracleResultSet)rs).getBLOB("detail");
InputStream in = blob.getBinaryStream();  // 而非 rs.getBinaryStream()

替代方案:使用 LONG RAW

標準 JDBC 支援:ps.setBinaryStream(1, fin, len) 直接寫入,但 LONG RAW 已不推薦使用(單表僅一欄、操作限制多)。

三、可捲動結果集陷阱

  • Oracle 不支援伺服器端可捲動游標。
  • JDBC 2.0 ResultSet.TYPE_SCROLL_INSENSITIVE 是在**客戶端記憶體全量緩存**實現。
  • 大量資料(數萬列以上)會導致 OOM,嚴禁用於大結果集。
  • 大資料集請使用前向游標分頁查詢(ROWNUM 或 OFFSET/FETCH 12c+)。

小結

Java/Oracle 開發鐵律:用 registerDriver 載入驅動、BLOB 必須用 Oracle 擴充 API、可捲動結果集僅限小結果集、大數據分頁在 SQL 層解決。

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