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

JDBC 與 Hibernate 寫入 Oracle BLOB 欄位完整範例

     編輯:Oracle 資料庫相關知識

Oracle BLOB 欄位效能優於 LONG,適合儲存圖片等二進位資料。寫入方式特殊:必須先插入 EMPTY_BLOB() 取得定位器,再透過輸出流寫入資料。本文提供完整 JDBC 範例,Hibernate 同理。

核心步驟

  1. 關閉自動提交:conn.setAutoCommit(false)
  2. 插入空 BLOB 取得定位器:INSERT INTO javatest(name, content) VALUES (?, EMPTY_BLOB())
  3. SELECT content FROM javatest WHERE name=? FOR UPDATE 取得 oracle.sql.BLOB 物件
  4. 呼叫 blob.getBinaryOutputStream() 取得輸出流
  5. 將檔案資料寫入輸出流
  6. 關閉流、提交交易

完整 JDBC 程式碼

import java.sql.*;
import java.io.*;
import oracle.sql.*;

public class WriteBlob {
  public static void main(String[] args) {
    try {
      DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
      Connection conn = DriverManager.getConnection(
        "jdbc:oracle:thin:@localhost:1521:orcl", "fankai", "fankai");
      conn.setAutoCommit(false);

      // 1. 插入空 BLOB
      PreparedStatement pstmt = conn.prepareStatement(
        "INSERT INTO javatest(name, content) VALUES (?, EMPTY_BLOB())");
      pstmt.setString(1, "fankai");
      pstmt.executeUpdate();
      pstmt.close();

      // 2. 取得 BLOB 定位器
      pstmt = conn.prepareStatement(
        "SELECT content FROM javatest WHERE name = ? FOR UPDATE");
      pstmt.setString(1, "fankai");
      ResultSet rset = pstmt.executeQuery();
      BLOB blob = null;
      if (rset.next()) blob = (BLOB) rset.getBlob(1);
      pstmt.close(); rset.close();

      // 3. 寫入檔案資料
      String fileName = "oraclejdbc.jar";
      File f = new File(fileName);
      FileInputStream fin = new FileInputStream(f);
      System.out.println("file size = " + fin.available());

      OutputStream out = blob.getBinaryOutputStream();
      byte[] data = new byte[(int) fin.available()];
      fin.read(data);
      out.write(data);
      fin.close(); out.close();

      conn.commit();
      conn.close();
      System.out.println("BLOB 寫入完成");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

記憶體優化寫法(大檔案)

byte[] data = new byte[blob.getBufferSize()];
int count, total = 0;
while ((count = fin.read(data)) != -1) {
  total += count;
  out.write(data, 0, count);
}

Hibernate 對應

實體類別欄位型別用 java.sql.Blob 或 byte[](配合 @Lob),Session 操作邏輯相同:先 save() 取得 ID,再 lock() 為 LockMode.UPGRADE 取得 Blob 物件寫入。建議使用 Hibernate 的 LobCreator API 簡化流程。


關鍵提醒:務必使用 FOR UPDATE 鎖定列,否則取得的 BLOB 定位器無效;交易未提交前資料不可見。

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