前段时间到客户现场出差,www.devze.com在现场遇到了base64和图片互相转换的问题,在现场肯定不如自己安安静静写代码的时候冷静,为了解决问题几乎浪费了一整天,所以这篇文章也是为了梳理一下Java通过MyBATis操作oracle的Clob和Blob的解决方式和注意事项
首先我们要搞清楚CLOB和BLOB的区别,这两个被统称为LOB,即Large Object(大对象类型),最本质的区别
- CLOB的C,可以理解为Char(当然这种理解方式肯定不对),所以CLOB保存的是字符大对象
- BLOB的B,即Binary,保存的是二进制大对象
这时候我们就能大概理解了,如果我们要在Java中用编程数据类型去接,则
- CLOB应该转换成String
- BLOB应该转换成byte[]
那我们就可以大概模拟一下如何获得这些值,模拟一下当时我在现场遇到的情况
首先,我们实际操作的,都是一张图片,这张图片在BLOB中保存,可以直接保存,即在plsql中,也能通过查看详情的方式查看图片
在CLOB中保存,应该是一个base64的字符串
单纯考虑获取,我们可以简单集成Mybatis,用Map<String, Object>直接接住获取的数据,如图所示
@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"; }
我们先看看,如果只通过这种方式获取,获取出来的数据是什么样子的
可以看到,获取到的数据没有以[B开头,说明这并不是byte数组,而是包装过的,那很简单,我们使用相应的格式再接一下就可以了
Blob blob = (Blob)map.get("BLOB"); Clob clob = (Clob)map.get("CLOB");
这个时候可能会有同学发现,Blob和Clob这两个类分别对应了两个包的内容
莫担心,oracle.sql.Blob实现了java.sql.Blob,里面的方法名和参数都是一样,Clob也是一样,单纯使用的话感觉不到什么区别
按照之前所说,BLOB应该用byte[]来接,CLOB应该用String来接,这时候就遇到了我查资料时出现的各种问题
在很多人的博客中,不管是BLOB转byte[],还是CLOB转String,都是通过流的方式去进行的,这里也给大家提供一下别人的代码,亲测用是可以用的
/** * BLOB转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转String * @param clob * @return */ public static String clobToString(Clob clob) { try { Reader inStreamDoc = clob.getCharacterStream(); char[] tempDoc = new char[(int) clob.lpythonength()]; inStreamDoc.read(tempDoc); inStreamDoc.close(); return new String(tempDoc); } catch (IOException e) { e.printStackTrace(); } catch (SQLException es) { es.printStackTrace(); } return null; }
这个时候就很令人费解,为什么都约定了BLOB和CLOB是什么样的数据,但还要使用流的方式来接呢,这时候,就要看看Blob这个类本身有没有提供什么方法,只要点进源码,赫然可以看到
这就尴尬了,难道是这种自带的方法有问题?带着疑问,让我们来看看到底能不能用
注意上边的两个方法注释中都写明了,第一个参数pos的值,应该从1开始
首先是BLOB的转换,因为是图片,我们统一转换成base64字符串再对android比一下
@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()); //流转byte[] byte[] bytes2 = blobToBytes((Blob)map.get("BLOB")); System.err.prinphptln("result===="+ DatatypeConverter.printBase64Binary(bytes2).equals(DatatypeConverter.printBase64Binary(bytes1))); return "success"; }
充分证明了流转byte[]和自带的getBytes方法没有任何区别
那CLOB也是如此吗
CLOB直接保存的就是base64字符串,直接对比就好
@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()); //流转String String clobStr2 = clobToString(clob); System.err.println("result===="+ clobStr2.equals(clobStr1)); return "success"; }
CLOB的转换也是没问题的
所以最终确定,操作BLOB和CLOB,直接使用类自带的方法就可以了
到此这篇关于Java通过Mybatis操作Oracle的Clob和Blob的文章就介绍到这了,更多相关mybatis oracle Clob和Blob内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论