Oracle LOB
LOB,即Large Objects(大對象),是用來存儲大量的二進制和文本數據的一種數據類型(一個LOB字段可存儲可多達4GB的數據)。
LOB 分為兩種類型:內部LOB和外部LOB。
內部LOB將數據以字節流的形式存儲在數據庫的內部。因而,內部LOB的許多操作都可以參與事務,也可以像處理普通數據一樣對其進行備份和恢復操作。Oracle支持三種類型的內部LOB:
- BLOB(二進制數據)
- CLOB(單字節字符數據)
- NCLOB(多字節字符數據)。
CLOB和NCLOB類型適用於存儲超長的文本數據,BLOB字段適用於存儲大量的二進制數據,如圖像、視頻、音頻,文件等。
目前只支持一種外部LOB類型,即BFILE類型。在數據庫內,該類型僅存儲數據在操作系統中的位置信息,而數據的實體以外部文件的形式存在於操作系統的文件系統中。因而,該類型所表示的數據是只讀的,不參與事務。該類型可幫助用戶管理大量的由外部程序訪問的文件。
MySQL BLOB
MySQL中,BLOB是一個二進制大型對象,是一個可以存儲大量數據的容器,它能容納不同大小的數據。
MySQL的四種BLOB類型(除了在存儲的最大信息量上不同外,他們是等同的)。
實際使用中根據需要存入的數據大小定義不同的BLOB類型。需要注意的是:如果存儲的文件過大,數據庫的性能會下降。
使用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數據了。
步驟
- 插入空blob insert into javatest(name,content) values(?,empty_blob());
- 獲得blob的cursor select content from javatest where name= ? for update; 注意: 須加for update,鎖定該行,直至該行被修改完畢,保證不產生並發沖突。
- 利用 io,和獲取到的cursor往數據庫寫數據流 。
插入 BLOB 類型的數據必須使用 PreparedStatement:因為 BLOB 類型的數據時無法使用字符串拼寫的。
舉個例子:
public void testInsertBlob(){ Connection connection = null; PreparedStatement preparedStatement = null; try { connection = JDBCTools.getConnection(); String sql = "INSERT INTO customers(name, email, birth, picture)" + "VALUES(?,?,?,?)"; preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, "ABCDE"); preparedStatement.setString(2, "abcde@atguigu.com"); preparedStatement.setDate(3, new Date(new java.util.Date().getTime())); InputStream inputStream = new FileInputStream("Hydrangeas.jpg"); preparedStatement.setBlob(4, inputStream); preparedStatement.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally{ JDBCTools.releaseDB(null, preparedStatement, connection); } }
讀取 blob 數據:
1. 使用 getBlob 方法讀取到 Blob 對象
2. 調用 Blob 的 getBinaryStream() 方法得到輸入流。再使用 IO 操作即可.
舉個例子:
@Test public void readBlob(){ Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = JDBCTools.getConnection(); String sql = "SELECT id, name customerName, email, birth, picture " + "FROM customers WHERE id = 13"; preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); if(resultSet.next()){ int id = resultSet.getInt(1); String name = resultSet.getString(2); String email = resultSet.getString(3); System.out.println(id + ", " + name + ", " + email); Blob picture = resultSet.getBlob(5); InputStream in = picture.getBinaryStream(); System.out.println(in.available()); OutputStream out = new FileOutputStream("flower.jpg"); byte [] buffer = new byte[1024]; int len = 0; while((len = in.read(buffer)) != -1){ out.write(buffer, 0, len); } in.close(); out.close(); } } catch (Exception e) { e.printStackTrace(); } finally{ JDBCTools.releaseDB(resultSet, preparedStatement, connection); } }