jdbc中如何處理Oracle BLOB欄位

來源:互聯網
上載者:User
jdbc中如何處理Oracle BLOB欄位

2006-09-22   來源:JAVA資源網  作者:郝從平

jdbc中如何處理Oracle BLOB欄位

為什麼我要寫這篇文章?

在前段時間我所在的項目中,就碰到了這個問題,我花了2天的時間才將BLOB的問題搞定。我也嘗試過網上所介紹的各種方法,那些方法所使用的原理都一致,但都寫得不完整,我也按照網上介紹的方法做了,但都因為其中一些沒有提到的小的細節而失敗。希望看到這篇文章的人都不再走彎路。

一般人會走哪些彎路?
1.使用jdk中的方法進行傳輸。在ResultSet 中有getBlob()方法,在PreparedStatement中有setBlob()方法,所以大多數人都會嘗試setBlob(),getBlob() 進行讀寫,或者兩個資料庫之間BLOB的傳輸。這種方法實際上是行不通的,據網上的一些資料介紹,說sun官方的文檔有些方法都是錯誤的。

2.使用ResultSet.getBinaryStream 和PreparedStatement.setBinaryStream對BLOB進行讀寫或兩個資料庫間的傳輸。這種方法我自己嘗試過,發現,如果BLOB中儲存的是文字檔的話,就沒問題,如果是二進位檔案,傳輸就會有問題。

根據自己的經驗,以及查閱了Oracle的官方文檔,都是使用如下處理方法:
1.建立記錄,插入BLOB資料
 1.1首先建立記錄的時候,使用oracle的函數插入一個空的BLOB,假設欄位A是BLOB類型的:
  insert xxxtable(A,B,C) values(empty_blob(),'xxx','yyyy')
 1.2後面再查詢剛才插入的記錄,然後更新BLOB,在查詢前,注意設定Connection的一個屬性:
  conn.setAutoCommit(false);如果缺少這一步,可能導致fetch out of sequence等異常.
 1.3 查詢剛才插入的記錄,後面要加“ for update ”,如下:
  select A from xxxtable where xxx=999 for update ,如果缺少for update,可能出現row containing the LOB value is not locked的異常
 1.4 從查詢到的 BLOB欄位中,擷取blob並進行更新,代碼如下:
  BLOB blob = (BLOB) rs.getBlob("A");
  OutputStream os = blob.getBinaryOutputStream();
  BufferedOutputStream output = new BufferedOutputStream(os);

  後面再使用output.write方法將需要寫入的內容寫到output中就可以了。例如我們將一個檔案寫入這個欄位中:
BufferedInputStream input = new BufferedInputStream(new File("c://hpWave.log").toURL().openStream());
byte[] buff = new byte[2048];  //用做檔案寫入的緩衝
int bytesRead;
while(-1 != (bytesRead = input.read(buff, 0, buff.length))) {
output.write(buff, 0, bytesRead);
System.out.println(bytesRead);
}
  上面的代碼就是從input裡2k地讀取,然後寫入到output中。
 1.5上面執行完畢後,記得關閉output,input,以及關閉查詢到的ResultSet
 1.6最後執行conn.commit();將更新的內容提交,以及執行conn.setAutoCommit(true); 改回Connction的屬性
2.修改記錄,方法與上面的方法類似,
 2.1首先更新BLOB以外的其他欄位
 2.2 使用1.3中類似的方法擷取記錄
 2.3 修改的過程中,注意以下:a 需要更新的記錄中,BLOB有可能為NULL,這樣在執行blob.getBinaryOutputStream()擷取的值可能為null,那麼就關閉剛才select的記錄,再執行一次update xxxtable set A = empty_blob() where xxx, 這樣就先寫入了一個空的BLOB(不是null),然後再使用1.3,1.4中的方法執行更新記錄.b 注意別忘了先執行setAutoCommit(false),以及"for update",以及後面的conn.commit();等。
3.讀取BLOB欄位中的資料.
 3.1 讀取記錄不需要setAutoCommit(),以及 select ....for update.
 3.2 使用普通的select 方法查詢出記錄
 3.3 從ResultSet中擷取BLOB並讀取,如下:
  BLOB b_to = (BLOB) rs.getBlob("A");
  InputStream is = b_from.getBinaryStream();
  BufferedInputStream input = new BufferedInputStream(is);
  byte[] buff = new byte[2048];
  while(-1 != (bytesRead = input.read(buff, 0, buff.length))) {
   //在這裡執行寫入,如寫入到檔案的BufferedOutputStream裡
   System.out.println(bytesRead);
  }
  通過迴圈取出blob中的資料,寫到buff裡,再將buff的內容寫入到需要的地方
4.兩個資料庫間blob欄位的傳輸
類似上面1和3的方法,一邊擷取BufferedOutputStream,另外一邊擷取BufferedInputStream,然後讀出寫入,需要注意的是寫入所用的Connection要執行conn.setAutoCommit(false);以及擷取記錄時添加“ for update ”以及最後的commit();

總結以上方法,其根本就是先建立空的BLOB,再擷取其BufferedOutputStream進行寫入,或擷取BufferedInputStream進行讀取

郝從平 email:cqhcp@126.com

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.