| 方式 | 代碼 | 優點 | 缺點/避坑 |
|---|---|---|---|
| Class.forName | Class.forName("oracle.jdbc.OracleDriver") | 簡單、標準 JDBC | MS JVM (IE Applet) 無法正確初始化靜態塊 |
| 系統屬性文件 | System.getProperties().load(...) 配置 jdbc.drivers=oracle.jdbc.OracleDriver | 解耦驅動類名、多驅動並行、無需改代碼換庫 | 需確保屬性文件在 Classpath、加載時機 |
| DriverManager.registerDriver | DriverManager.registerDriver(new oracle.jdbc.OracleDriver()) | 最可靠、任何環境 (含 Applet) 均可用 | 硬編碼驅動類、靈活性最低 |
建議: 現代應用 (Spring Boot 等) 由連接池 (HikariCP/Druid) 自動加載,無需手工編寫。
-- 錯誤嘗試
pstmt.setBinaryStream(1, inputStream, length); -- 針對 LONG RAW,非 BLOB
-- 會拋 IO Exception 而非 SQLException
// 1. 插入空 BLOB 佔位
conn.setAutoCommit(false);
stmt.executeUpdate("INSERT INTO tb_file(name, detail) VALUES ('a.gif', EMPTY_BLOB())");
// 2. 查回 BLOB 定位器 (FOR UPDATE 鎖定)
ResultSet rs = stmt.executeQuery("SELECT detail FROM tb_file WHERE name='a.gif' FOR UPDATE");
rs.next();
BLOB blob = ((OracleResultSet)rs).getBLOB(1); // 或 rs.getBlob(1) 強轉
// 3. 獲取輸出流寫入
try (OutputStream out = blob.setBinaryStream(1); // 1-based 位置
InputStream in = new FileInputStream(file)) {
byte[] buf = new byte[blob.getBufferSize()];
int len;
while ((len = in.read(buf)) != -1) out.write(buf, 0, len);
}
conn.commit();
Blob blob = rs.getBlob("detail");
try (InputStream in = blob.getBinaryStream()) {
// 處理輸入流
}
關鍵點: 必須 FOR UPDATE 鎖定行、關閉自動提交、使用 Oracle 擴展類 (oracle.sql.BLOB) 獲取流。
正確姿勢:
OFFSET/FETCH 或 ROWNUM) 推回數據庫。setFetchSize(1000) + 循環 rs.next() 逐行消費,不緩存全量。dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@(DESCRIPTION=...)");
dataSource.setUsername("app");
dataSource.setPassword("pwd");
dataSource.setMaximumPoolSize(20);
dataSource.setMinimumIdle(5);
dataSource.setConnectionTimeout(5000);
dataSource.setIdleTimeout(300000);
dataSource.setMaxLifetime(1200000);
dataSource.setConnectionInitSql("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");