Java通過(guò)Mybatis操作Oracle的Clob和Blob的解決方式
前段時(shí)間到客戶(hù)現(xiàn)場(chǎng)出差,在現(xiàn)場(chǎng)遇到了base64和圖片互相轉(zhuǎn)換的問(wèn)題,在現(xiàn)場(chǎng)肯定不如自己安安靜靜寫(xiě)代碼的時(shí)候冷靜,為了解決問(wèn)題幾乎浪費(fèi)了一整天,所以這篇文章也是為了梳理一下Java通過(guò)Mybatis操作Oracle的Clob和Blob的解決方式和注意事項(xiàng)
首先我們要搞清楚CLOB和BLOB的區(qū)別,這兩個(gè)被統(tǒng)稱(chēng)為L(zhǎng)OB,即Large Object(大對(duì)象類(lèi)型),最本質(zhì)的區(qū)別
- CLOB的C,可以理解為Char(當(dāng)然這種理解方式肯定不對(duì)),所以CLOB保存的是字符大對(duì)象
- BLOB的B,即Binary,保存的是二進(jìn)制大對(duì)象
這時(shí)候我們就能大概理解了,如果我們要在Java中用數(shù)據(jù)類(lèi)型去接,則
- CLOB應(yīng)該轉(zhuǎn)換成String
- BLOB應(yīng)該轉(zhuǎn)換成byte[]
那我們就可以大概模擬一下如何獲得這些值,模擬一下當(dāng)時(shí)我在現(xiàn)場(chǎng)遇到的情況
首先,我們實(shí)際操作的,都是一張圖片,這張圖片在BLOB中保存,可以直接保存,即在plsql中,也能通過(guò)查看詳情的方式查看圖片
在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"; }
我們先看看,如果只通過(guò)這種方式獲取,獲取出來(lái)的數(shù)據(jù)是什么樣子的
可以看到,獲取到的數(shù)據(jù)沒(méi)有以[B開(kāi)頭,說(shuō)明這并不是byte數(shù)組,而是包裝過(guò)的,那很簡(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è)類(lèi)分別對(duì)應(yīng)了兩個(gè)包的內(nèi)容
莫擔(dān)心,oracle.sql.Blob實(shí)現(xiàn)了java.sql.Blob,里面的方法名和參數(shù)都是一樣,Clob也是一樣,單純使用的話(huà)感覺(jué)不到什么區(qū)別
按照之前所說(shuō),BLOB應(yīng)該用byte[]來(lái)接,CLOB應(yīng)該用String來(lái)接,這時(shí)候就遇到了我查資料時(shí)出現(xiàn)的各種問(wèn)題
在很多人的博客中,不管是BLOB轉(zhuǎn)byte[],還是CLOB轉(zhuǎn)String,都是通過(guò)流的方式去進(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ù),但還要使用流的方式來(lái)接呢,這時(shí)候,就要看看Blob這個(gè)類(lèi)本身有沒(méi)有提供什么方法,只要點(diǎn)進(jìn)源碼,赫然可以看到
這就尷尬了,難道是這種自帶的方法有問(wèn)題?帶著疑問(wèn),讓我們來(lái)看看到底能不能用
注意上邊的兩個(gè)方法注釋中都寫(xiě)明了,第一個(gè)參數(shù)pos的值,應(yīng)該從1開(kāi)始
首先是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方法沒(méi)有任何區(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)換也是沒(méi)問(wèn)題的
所以最終確定,操作BLOB和CLOB,直接使用類(lèi)自帶的方法就可以了
到此這篇關(guān)于Java通過(guò)Mybatis操作Oracle的Clob和Blob的文章就介紹到這了,更多相關(guān)mybatis oracle Clob和Blob內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud Feign請(qǐng)求添加headers的實(shí)現(xiàn)方式
這篇文章主要介紹了Spring Cloud Feign請(qǐng)求添加headers的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04SpringBoot集成P6spy實(shí)現(xiàn)自定義SQL日志打印
本文主要介紹了SpringBoot集成P6spy實(shí)現(xiàn)自定義SQL日志打印,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Java 關(guān)于String字符串原理上的問(wèn)題
字符串廣泛應(yīng)用 在 Java 編程中,在 Java 中字符串屬于對(duì)象,Java 提供了 String 類(lèi)來(lái)創(chuàng)建和操作字符串,讓我們一起來(lái)了解它2022-04-04詳解Spring MVC3返回JSON數(shù)據(jù)中文亂碼問(wèn)題解決
本篇文章主要介紹了Spring MVC3返回JSON數(shù)據(jù)中文亂碼問(wèn)題解決,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01SpringCloud Feign 服務(wù)調(diào)用的實(shí)現(xiàn)
Feign是一個(gè)聲明性web服務(wù)客戶(hù)端。本文記錄多個(gè)服務(wù)之間使用Feign調(diào)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-01-01Spring中的@AutoWired與@Resource及@Qualifier注解詳解
這篇文章主要介紹了Spring中的@AutoWired與@Resource及@Qualifier注解詳解,spring不但支持自己定義的@Autowired注解,所以Autowired與Spring是強(qiáng)相關(guān)性,只能在spring框架中使用,而后幾個(gè)注解則不然,需要的朋友可以參考下2023-11-11Spring Bean的初始化和銷(xiāo)毀實(shí)例詳解
這篇文章主要介紹了Spring Bean的初始化和銷(xiāo)毀,結(jié)合實(shí)例形式詳細(xì)分析了Spring Bean的初始化和銷(xiāo)毀相關(guān)配置、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2019-11-11java并發(fā)編程之進(jìn)程和線(xiàn)程調(diào)度基礎(chǔ)詳解
這篇文章主要介紹了java并發(fā)編程之進(jìn)程和線(xiàn)程調(diào)度基礎(chǔ),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Spring?Boot日志SLF4J和Logback示例詳解
這篇文章主要介紹了Spring?Boot日志SLF4J和Logback詳解,Logback相比于Log4j,性能提高了10倍以上的性能,占用的內(nèi)存也變小了,并且文檔十分詳細(xì),推薦使用Slf4j+Logback,需要的朋友可以參考下2023-07-07