Oracle BLOB (Binary Large Object) 儲存二進位檔案是常見需求,但 JDBC 標準介面與 Oracle 專屬實作常有相容性問題。本文提供完整建表、Java 讀寫範例、關鍵 API 解析與最佳實務,助你穩定處理大物件資料。
DROP TABLE filelist;
CREATE TABLE SYSTEM.FILELIST (
"FILENAME" VARCHAR2(50) NOT NULL,
"FILESIZE" NUMBER(20),
"FILEBODY" BLOB,
PRIMARY KEY ("FILENAME")
);
EMPTY_BLOB() 初始化 BLOB 欄位oracle.sql.BLOB 物件putBytes(pos, bytes[]) 寫入getBytes(pos, length) 或串流 API// 1. 插入控制資料並初始化 BLOB
String sql = "INSERT INTO filelist (FileName, FileSize, FileBody) VALUES (?, ?, EMPTY_BLOB())";
OraclePreparedStatement opst = (OraclePreparedStatement) conn.prepareStatement(sql);
opst.setString(1, "Wordtemplate");
opst.setInt(2, fileLength);
opst.executeUpdate();
// 2. 定位 BLOB 進行寫入
sql = "SELECT filebody FROM filelist WHERE filename=? FOR UPDATE";
opst = (OraclePreparedStatement) conn.prepareStatement(sql);
opst.setString(1, "Wordtemplate");
OracleResultSet ors = (OracleResultSet) opst.executeQuery();
if (ors.next()) {
BLOB blob = ors.getBLOB(1);
int written = blob.putBytes(1, fileBytes); // 從位置 1 開始寫入
conn.commit();
}
sql = "SELECT filebody FROM filelist WHERE filename=?";
opst = (OraclePreparedStatement) conn.prepareStatement(sql);
opst.setString(1, "Wordtemplate");
ors = (OracleResultSet) opst.executeQuery();
if (ors.next()) {
BLOB blob = ors.getBLOB(1);
byte[] data = blob.getBytes(1, (int) blob.length()); // 一次讀完
// 或使用串流處理大檔案
// InputStream is = blob.getBinaryStream();
// OutputStream os = new FileOutputStream("output.doc");
// byte[] buf = new byte[4096]; int len;
// while ((len = is.read(buf)) != -1) os.write(buf, 0, len);
}
| 功能 | 位元組陣列 API | 串流 API (大檔案推薦) |
|---|---|---|
| 寫入 | putBytes(long pos, byte[] bytes) | getBinaryOutputStream() |
| 讀取 | getBytes(long pos, int length) | getBinaryStream() |
oracle.sql.BLOB, OraclePreparedStatement, OracleResultSet,標準 JDBC 介面常失效。EMPTY_BLOB() 建立定位器。FOR UPDATE 取得鎖定,否則 putBytes 會拋例外。conn.commit() 持久化。掌握 Oracle BLOB 專屬 API 與交易控制,能穩定實現檔案資料庫化儲存。