DriverManager 註冊驅動。但 Microsoft JVM (IE Applet) 無法正確初始化,慎用。jdbc.drivers=oracle.jdbc.driver.OracleDriver,支援多驅動、不改代碼切換資料庫,彈性最佳。建議:生產環境優先考慮屬性檔或 registerDriver,避免 Class.forName 在特定容器失效。
網上 99% 教程(含 Sun 早期文檔)對 Oracle BLOB 處理有誤導。關鍵點:
setBinaryStream 寫入 BLOB,會拋 IO 異常而非 SQL 異常。LONG RAW 欄位,配合 PreparedStatement.setBinaryStream() 直接寫入。// 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、游標迴圈),勿用可捲動結果集。
| 場景 | 推薦做法 | 避坑關鍵 |
|---|---|---|
| 驅動載入 | 屬性檔 / registerDriver | Applet 環境禁用 Class.forName |
| 二進制大檔 | LONG RAW + setBinaryStream | 標準 JDBC 不支援直寫 BLOB |
| BLOB 正統用法 | empty_blob() + FOR UPDATE + 專有 API | 同一事務、先 SELECT 再寫入 |
| 海量查詢 | 分頁 SQL / 伺服器端游標 | 禁用 TYPE_SCROLL_* 防 OOM |