首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JDBC 與 Hibernate 操作 CLOB/BLOB 字段深度對比:從類型映射到代碼實戰

     編輯:Java 程式設計入門

大對象字段(CLOB/BLOB)在不同數據庫、不同持久層框架中類型映射與操作 API 差異較大。本文系統梳理類型對應關係,並給出 JDBC 原生與 Hibernate 兩套完整代碼範例。

一、類型映射對照表

場景CLOB 對應BLOB 對應
MySQL 列類型TEXT / LONGTEXTBLOB / LONGBLOB
Oracle/DB2 列類型CLOBBLOB
Java 領域類型String / java.sql.Clobbyte[] / java.sql.Blob
Hibernate 映射類型clob / materialized_clobblob / materialized_blob
廠商擴展類型oracle.sql.CLOBoracle.sql.BLOB

二、JDBC 原生操作(以 Oracle 為例)

1. CLOB 寫入:兩階段「插空值 → 鎖行 → 寫流」

conn.setAutoCommit(false);
// 階段 1:插入 EMPTY_CLOB()
PreparedStatement ps = conn.prepareStatement(
    "insert into files(name, content) values(?, EMPTY_CLOB())");
ps.setString(1, "jack");
ps.executeUpdate();

// 階段 2:SELECT ... FOR UPDATE 鎖定行
ps = conn.prepareStatement("select content from files where name=? for update");
ps.setString(1, "jack");
ResultSet rs = ps.executeQuery();
rs.next();
oracle.sql.Clob clob = (oracle.sql.Clob) rs.getClob(1);

// 寫入字符流
try (Writer w = clob.getCharacterOutputStream()) {
    w.write(longTextContent);
}
conn.commit();

2. CLOB 讀取

oracle.sql.Clob clob = (oracle.sql.Clob) rs.getClob("content");
if (clob != null) {
    try (Reader r = clob.getCharacterStream();
         BufferedReader br = new BufferedReader(r)) {
        String line, content = "";
        while ((line = br.readLine()) != null) content += line + "
"; } }

3. BLOB 寫入:二進制流

ps = conn.prepareStatement("insert into photos(name, data) values(?, empty_blob())");
ps.setString(1, "jack"); ps.executeUpdate();

ps = conn.prepareStatement("select data from photos where name=? for update");
ps.setString(1, "jack");
rs = ps.executeQuery(); rs.next();
oracle.sql.Blob blob = (oracle.sql.Blob) rs.getBlob(1);

try (OutputStream out = blob.getBinaryOutputStream();
     FileInputStream fin = new FileInputStream("c:\\test.rar")) {
    byte[] buf = new byte[blob.getBufferSize()];
    int len;
    while ((len = fin.read(buf)) != -1) out.write(buf, 0, len);
}
conn.commit();

三、Hibernate 操作(原理相同,API 更高級)

1. CLOB

Session session = ...;
Transaction tx = session.beginTransaction();
MyFile f = new MyFile(); f.setName("jack");
f.setContent(Hibernate.createClob("")); // 插入空 CLOB
session.save(f);
session.flush();
session.refresh(f, LockMode.UPGRADE); // 相當於 SELECT ... FOR UPDATE

oracle.sql.Clob clob = (oracle.sql.Clob) f.getContent();
try (Writer w = clob.getCharacterOutputStream()) {
    w.write(longText);
}
tx.commit();

2. BLOB

Photo p = new Photo(); p.setName("jack");
p.setPhoto(Hibernate.createBlob(new byte[0])); // 空 BLOB
session.save(p);
session.flush();
session.refresh(p, LockMode.UPGRADE);

oracle.sql.Blob blob = (oracle.sql.Blob) p.getPhoto();
try (OutputStream out = blob.getBinaryOutputStream();
     FileInputStream fin = new FileInputStream("c:\\test.rar")) {
    byte[] data = new byte[fin.available()];
    fin.read(data);
    out.write(data);
}
session.flush();

四、關鍵差異與選型建議

  • JDBC:完全控制,適合批量導入、存儲過程、非標準數據庫類型;代碼冗長,需手動管理鎖與流。
  • Hibernate:Hibernate.createClob/Blob + refresh(LockMode.UPGRADE) 封裝了兩階段邏輯,領域模型更純淨;但綁定廠商實現類(oracle.sql.Clob)影響可移植性。
  • 可移植性提升:Hibernate 5.2+ 支持 @Lob + @JdbcTypeCode(SqlTypes.CLOB),配合標準 java.sql.Clob 接口,減少強轉。

五、MySQL 特別說明

MySQL TEXT/BLOB 類型無需「空值+鎖行」兩階段,可直接 ps.setString()/ps.setBytes() 或 Hibernate @Lob String/byte[] 透明持久化。但超大對象(>16MB)仍建議分流存儲(對象存儲/文件系統 + DB 存路徑)。

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