Java通過Mybatis操作Oracle的Clob和Blob的解決方式
前段時(shí)間到客戶現(xiàn)場(chǎng)出差,在現(xiàn)場(chǎng)遇到了base64和圖片互相轉(zhuǎn)換的問題,在現(xiàn)場(chǎng)肯定不如自己安安靜靜寫代碼的時(shí)候冷靜,為了解決問題幾乎浪費(fèi)了一整天,所以這篇文章也是為了梳理一下Java通過Mybatis操作Oracle的Clob和Blob的解決方式和注意事項(xiàng)
首先我們要搞清楚CLOB和BLOB的區(qū)別,這兩個(gè)被統(tǒng)稱為L(zhǎng)OB,即Large Object(大對(duì)象類型),最本質(zhì)的區(qū)別
- CLOB的C,可以理解為Char(當(dāng)然這種理解方式肯定不對(duì)),所以CLOB保存的是字符大對(duì)象
- BLOB的B,即Binary,保存的是二進(jìn)制大對(duì)象
這時(shí)候我們就能大概理解了,如果我們要在Java中用數(shù)據(jù)類型去接,則
- CLOB應(yīng)該轉(zhuǎn)換成String
- BLOB應(yīng)該轉(zhuǎn)換成byte[]
那我們就可以大概模擬一下如何獲得這些值,模擬一下當(dāng)時(shí)我在現(xiàn)場(chǎng)遇到的情況
首先,我們實(shí)際操作的,都是一張圖片,這張圖片在BLOB中保存,可以直接保存,即在plsql中,也能通過查看詳情的方式查看圖片

在CLOB中保存,應(yīng)該是一個(gè)base64的字符串

單純考慮獲取,我們可以簡(jiǎn)單集成Mybatis,用Map<String, Object>直接接住獲取的數(shù)據(jù),如圖所示

@RequestMapping("getArr/{id}")
public String getArr(@PathVariable String id) throws SQLException {
Map<String, Object> map = byteArrayTestService.find(id);
System.err.println("------------------");
System.err.println("map:"+map);
return "success";
}我們先看看,如果只通過這種方式獲取,獲取出來的數(shù)據(jù)是什么樣子的

可以看到,獲取到的數(shù)據(jù)沒有以[B開頭,說明這并不是byte數(shù)組,而是包裝過的,那很簡(jiǎn)單,我們使用相應(yīng)的格式再接一下就可以了
Blob blob = (Blob)map.get("BLOB");
Clob clob = (Clob)map.get("CLOB");這個(gè)時(shí)候可能會(huì)有同學(xué)發(fā)現(xiàn),Blob和Clob這兩個(gè)類分別對(duì)應(yīng)了兩個(gè)包的內(nèi)容

莫擔(dān)心,oracle.sql.Blob實(shí)現(xiàn)了java.sql.Blob,里面的方法名和參數(shù)都是一樣,Clob也是一樣,單純使用的話感覺不到什么區(qū)別
按照之前所說,BLOB應(yīng)該用byte[]來接,CLOB應(yīng)該用String來接,這時(shí)候就遇到了我查資料時(shí)出現(xiàn)的各種問題
在很多人的博客中,不管是BLOB轉(zhuǎn)byte[],還是CLOB轉(zhuǎn)String,都是通過流的方式去進(jìn)行的,這里也給大家提供一下別人的代碼,親測(cè)用是可以用的
/**
* BLOB轉(zhuǎn)byte[]
* @param blob
* @return
*/
private byte[] blobToBytes(Blob blob) {
BufferedInputStream is = null;
try {
is = new BufferedInputStream(blob.getBinaryStream());
byte[] bytes = new byte[(int) blob.length()];
int len = bytes.length;
int offset = 0;
int read = 0;
while (offset < len && (read = is.read(bytes, offset, len - offset)) >= 0) {
offset += read;
}
return bytes;
} catch (Exception e) {
return null;
} finally {
try {
is.close();
is = null;
} catch (IOException e) {
return null;
}
}
}
/**
* CLOB轉(zhuǎn)String
* @param clob
* @return
*/
public static String clobToString(Clob clob) {
try {
Reader inStreamDoc = clob.getCharacterStream();
char[] tempDoc = new char[(int) clob.length()];
inStreamDoc.read(tempDoc);
inStreamDoc.close();
return new String(tempDoc);
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException es) {
es.printStackTrace();
}
return null;
}這個(gè)時(shí)候就很令人費(fèi)解,為什么都約定了BLOB和CLOB是什么樣的數(shù)據(jù),但還要使用流的方式來接呢,這時(shí)候,就要看看Blob這個(gè)類本身有沒有提供什么方法,只要點(diǎn)進(jìn)源碼,赫然可以看到


這就尷尬了,難道是這種自帶的方法有問題?帶著疑問,讓我們來看看到底能不能用
注意上邊的兩個(gè)方法注釋中都寫明了,第一個(gè)參數(shù)pos的值,應(yīng)該從1開始
首先是BLOB的轉(zhuǎn)換,因?yàn)槭菆D片,我們統(tǒng)一轉(zhuǎn)換成base64字符串再對(duì)比一下
@RequestMapping("getArr/{id}")
public String getArr(@PathVariable String id) throws SQLException {
Map<String, Object> map = byteArrayTestService.find(id);
System.err.println("------------------");
Blob blob = (Blob)map.get("BLOB");
//Clob clob = (Clob)map.get("CLOB");
//自帶的方法
byte[] bytes1 = blob.getBytes(1, (int) blob.length());
//流轉(zhuǎn)byte[]
byte[] bytes2 = blobToBytes((Blob)map.get("BLOB"));
System.err.println("result===="+ DatatypeConverter.printBase64Binary(bytes2).equals(DatatypeConverter.printBase64Binary(bytes1)));
return "success";
}
充分證明了流轉(zhuǎn)byte[]和自帶的getBytes方法沒有任何區(qū)別
那CLOB也是如此嗎
CLOB直接保存的就是base64字符串,直接對(duì)比就好
@RequestMapping("getArr/{id}")
public String getArr(@PathVariable String id) throws SQLException {
Map<String, Object> map = byteArrayTestService.find(id);
System.err.println("------------------");
//Blob blob = (Blob)map.get("BLOB");
Clob clob = (Clob)map.get("CLOB");
//自帶的方法
String clobStr1 = clob.getSubString(1, (int) clob.length());
//流轉(zhuǎn)String
String clobStr2 = clobToString(clob);
System.err.println("result===="+ clobStr2.equals(clobStr1));
return "success";
}
CLOB的轉(zhuǎn)換也是沒問題的
所以最終確定,操作BLOB和CLOB,直接使用類自帶的方法就可以了
到此這篇關(guān)于Java通過Mybatis操作Oracle的Clob和Blob的文章就介紹到這了,更多相關(guān)mybatis oracle Clob和Blob內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Mybatis中的 ${ } 和 #{ }的區(qū)別使用詳解
這篇文章主要介紹了Mybatis中的 ${ } 和 #{ }的區(qū)別使用詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
基于數(shù)據(jù)庫的用戶認(rèn)證實(shí)現(xiàn)SpringBoot3整合SpringSecurity6的過程
這篇文章主要介紹了基于數(shù)據(jù)庫的用戶認(rèn)證實(shí)現(xiàn)SpringBoot3整合SpringSecurity6的過程,本文通過實(shí)例圖文并茂的形式給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-05-05
淺談Java方法調(diào)用的優(yōu)先級(jí)問題
這篇文章主要介紹了淺談Java方法調(diào)用的優(yōu)先級(jí)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
javaWeb如何實(shí)現(xiàn)隨機(jī)圖片驗(yàn)證碼詳解
這篇文章主要給大家介紹了關(guān)于javaWeb如何實(shí)現(xiàn)隨機(jī)圖片驗(yàn)證碼的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
基于javaMybatis存進(jìn)時(shí)間戳的問題
這篇文章主要介紹了javaMybatis存進(jìn)時(shí)間戳的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java創(chuàng)建,編輯與刪除Excel迷你圖表的實(shí)現(xiàn)方法
迷你圖是Excel工作表單元格中表示數(shù)據(jù)的微型圖表。本文將通過Java代碼示例介紹如何在Excel中創(chuàng)建迷你圖表,以及編輯和刪除表格中的迷你圖表,需要的可以參考一下2022-05-05
SpringBoot多租戶配置與實(shí)現(xiàn)示例
本文詳細(xì)介紹了在SpringBoot中實(shí)現(xiàn)多租戶架構(gòu)的方法和步驟,包括配置數(shù)據(jù)源、Hibernate攔截器、租戶解析器等,以共享數(shù)據(jù)庫、共享數(shù)據(jù)表的方式,確保數(shù)據(jù)隔離和安全性,感興趣的可以了解一下2024-09-09

