標籤:oracle jdbc java blob 儲存
LOB,即Large Objects(大對象),是用來儲存大量的二進位和文本資料的一種資料類型(一個LOB欄位可儲存可多達4GB的資料)。
LOB 分為兩種類型:內部LOB和外部LOB。
內部LOB將資料以位元組流的形式儲存在資料庫的內部。因而,內部LOB的許多操作都可以參與事務,
也可以像處理普通資料一樣對其進行備份和恢複操作。Oracle支援三種類型的內部LOB:
BLOB(位元據)
CLOB(單位元組字元資料)
NCLOB(多位元組字元資料)。
CLOB和NCLOB類型適用於儲存超長的文本資料,BLOB欄位適用於儲存大量的位元據,像、視頻、音頻,檔案等。
目前只支援一種外部LOB類型,即BFILE類型。在資料庫內,該類型僅儲存資料在作業系統中的位置資訊,
而資料的實體以外部檔案的形式存在於作業系統的檔案系統中。因而,該類型所表示的資料是唯讀,不參與事務。
該類型可協助使用者管理大量的由外部程式訪問的檔案.
使用JDBC來寫入Blob型資料到Oracle中 :
Oracle的Blob欄位比long欄位的效能要好,可以用來儲存片之類的位元據。
Oracle的BLOB欄位由兩部分組成:資料(值)和指向資料的指標(定位器)。儘管值與
表自身一起儲存,但是一個BLOB列並不包含值,僅有它的定位指標。為了使用大對象,程式必須聲明定位器類型的本地變數。
當Oracle內部LOB被建立時,定位器被存放在列中,值被存放在LOB段中,LOB段是在資料庫內部表的一部分。
因為Blob自身有一個cursor,當寫入Blob欄位必須使用指標(定位器)對Blob進行操作,因而在寫入Blob之前,
必須獲得指標(定位器)才能進行寫入
如何獲得Blob的指標(定位器) :需要先插入一個empty的blob,這將建立一個blob的指標,然後再把這個empty
的blob的指標查詢出來,這樣通過兩步操作,就獲得了blob的指標,可以真正的寫入blob資料了。
具體步驟:
1、插入空blob insert into javatest(name,content) values(?,empty_blob());
2、獲得blob的cursor select content from javatest where name= ? for update;
注意: 須加for update,鎖定該行,直至該行被修改完畢,保證不產生並發衝突。
3、利用 io,和擷取到的cursor往資料庫寫資料流
案例:以下案例實現插入一張圖片,和擷取有一張圖片的查詢結果;
/* * 檔案名稱:BlobTest.java * 著作權:Copyright by www.huawei.com * 描述: * 修改人:Cuigaochong * 修改時間:2015-8-25 * 跟蹤單號: * 修改單號: * 修改內容: */package com.jdbc.cgc.blob;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;import oracle.sql.BLOB;import org.junit.Test;/** * <一句話功能簡述> <功能詳細描述> * * @author 姓名 工號 * @version [版本號碼, 2015-8-25] * @see [相關類/方法] * @since [產品/模組版本] */public class BlobTest{ /** * <一句話功能簡述>測試方法,插入一條資料,資料中有一個列是Blob <功能詳細描述> * * @throws FileNotFoundException * @see [類、類#方法、類#成員] */ @Test public void test00() throws FileNotFoundException { // 注意: 對於empty_blob()應放在SQL語句中直接賦值, 使用預置語句的方式賦值無法實現. String sql = "insert into t_emp13(first_name,salary,picture) values (?,?,Empty_BLOB())"; // 查詢Blob 注意進行 行鎖定 後邊的for update String sqlQuery = "select picture from t_emp13 where first_name = ? and salary = ? for update"; updateBlob(sql, sqlQuery, "QQA122", 1233); } /** * <一句話功能簡述>更新有blob的資料庫表 <功能詳細描述> * * @param sqlInsert * @param sqlQuery * @param args * @see [類、類#方法、類#成員] */ public void updateBlob(String sqlInsert, String sqlQuery, Object... args) { Connection conn = null; PreparedStatement prepareStatement = null; ResultSet rs = null; OutputStream os = null; FileInputStream fis = null; try { // 現在表中插入空的Blob conn = getConn(); // 事物處理前,取消Connection的預設提交行為 conn.setAutoCommit(false); prepareStatement = conn.prepareStatement(sqlInsert); for (int i = 0; i < args.length; i++) { prepareStatement.setObject(i + 1, args[i]); } prepareStatement.executeUpdate(); BLOB blob = null; prepareStatement = conn.prepareStatement(sqlQuery); for (int i = 0; i < args.length; i++) { prepareStatement.setObject(i + 1, args[i]); } // prepareStatement.setString(1, "QQA"); rs = prepareStatement.executeQuery(); if (rs.next()) { blob = (BLOB)rs.getBlob(1); } // 得到資料庫的輸出資料流 os = blob.getBinaryOutputStream(); // 得到要插入檔案的輸入資料流 fis = new FileInputStream("Tulips.jpg"); byte[] b = new byte[1024]; int len; while (-1 != (len = fis.read(b))) { os.write(b, 0, len); } // 清空流的緩衝 os.flush(); // 事物處理:如果事物處理成功則提交事物 conn.commit(); } catch (Exception e) { e.printStackTrace(); try { // 事物處理:如果出現異常 則在catch塊中復原事物 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } releaseSource(prepareStatement, conn, null); } } /** * <一句話功能簡述>測試方法,查詢有blob的表 <功能詳細描述> * * @see [類、類#方法、類#成員] */ @Test public void test01() { String sql = "select picture from t_emp13 where first_name = ?"; queryBlob(sql, "QQA122"); } /** * <一句話功能簡述>查詢有Blob的表 方法 <功能詳細描述> * * @param sql * @param args * @see [類、類#方法、類#成員] */ public void queryBlob(String sql, Object... args) { Connection conn = null; PreparedStatement prepareStatement = null; ResultSet rs = null; FileOutputStream fos = null; InputStream is = null; try { conn = getConn(); // 事物處理前,取消Connection的預設提交行為 conn.setAutoCommit(false); prepareStatement = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { prepareStatement.setObject(i + 1, args[i]); } rs = prepareStatement.executeQuery(); if (rs.next()) { BLOB blob = (BLOB)rs.getBlob(1); is = blob.getBinaryStream(); fos = new FileOutputStream(new File("test.png")); byte[] b = new byte[1024]; int len; while (-1 != (len = is.read(b))) { fos.write(b, 0, len); } fos.flush(); } // 事物處理:如果事物處理成功則提交事物 conn.commit(); } catch (Exception e) { e.printStackTrace(); try { // 事物處理:如果出現異常 則在catch塊中復原事物 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } finally { if (null != is) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != fos) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } releaseSource(prepareStatement, conn, rs); } } /** * <一句話功能簡述> 串連資料庫 <功能詳細描述> * * @return * @throws Exception * @see [類、類#方法、類#成員] */ public Connection getConn() throws Exception { String dirverName = null; String jdbcUrl = null; String user = null; String password = null; Properties propertoes = new Properties(); InputStream is = getClass().getClassLoader().getResourceAsStream("jdbc.properties"); propertoes.load(is); dirverName = propertoes.getProperty("driver"); jdbcUrl = propertoes.getProperty("jdbcURL"); user = propertoes.getProperty("user"); password = propertoes.getProperty("password"); Class.forName(dirverName); // 通過DriverManager的getConnection擷取資料庫連接 Connection connection = DriverManager.getConnection(jdbcUrl, user, password); return connection; } /** * <一句話功能簡述>釋放資料庫資源 <功能詳細描述> * * @param statement * @param conn * @param resultSet * @see [類、類#方法、類#成員] */ public void releaseSource(Statement statement, Connection conn, ResultSet resultSet) { if (null != resultSet) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (null != statement) { try { statement.close(); } catch (Exception e) { e.printStackTrace(); } } if (null != conn) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } }}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
JDBC ORACLE BLOB處理