Java通过Mybatis操作Oracle的Clob和Blob的解决方式

 更新时间:2025年05月17日 09:50:19   作者:烤肉不拌饭  
这篇文章主要介绍了Java通过Mybatis操作Oracle的Clob和Blob的解决方式及注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

前段时间到客户现场出差,在现场遇到了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.length()];
        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字符串再对比一下

@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.println("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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Cloud Feign请求添加headers的实现方式

    Spring Cloud Feign请求添加headers的实现方式

    这篇文章主要介绍了Spring Cloud Feign请求添加headers的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • SpringBoot集成P6spy实现自定义SQL日志打印

    SpringBoot集成P6spy实现自定义SQL日志打印

    本文主要介绍了SpringBoot集成P6spy实现自定义SQL日志打印,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Java 关于String字符串原理上的问题

    Java 关于String字符串原理上的问题

    字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串,让我们一起来了解它
    2022-04-04
  • 详解Spring MVC3返回JSON数据中文乱码问题解决

    详解Spring MVC3返回JSON数据中文乱码问题解决

    本篇文章主要介绍了Spring MVC3返回JSON数据中文乱码问题解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • SpringCloud Feign 服务调用的实现

    SpringCloud Feign 服务调用的实现

    Feign是一个声明性web服务客户端。本文记录多个服务之间使用Feign调用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • Spring中的@AutoWired与@Resource及@Qualifier注解详解

    Spring中的@AutoWired与@Resource及@Qualifier注解详解

    这篇文章主要介绍了Spring中的@AutoWired与@Resource及@Qualifier注解详解,spring不但支持自己定义的@Autowired注解,所以Autowired与Spring是强相关性,只能在spring框架中使用,而后几个注解则不然,需要的朋友可以参考下
    2023-11-11
  • Spring Bean的初始化和销毁实例详解

    Spring Bean的初始化和销毁实例详解

    这篇文章主要介绍了Spring Bean的初始化和销毁,结合实例形式详细分析了Spring Bean的初始化和销毁相关配置、使用方法及操作注意事项,需要的朋友可以参考下
    2019-11-11
  • Java详细解析下拉菜单和弹出菜单的使用

    Java详细解析下拉菜单和弹出菜单的使用

    这篇文章主要介绍了怎么用Java来创建和使用下拉菜单和弹出菜单,下拉菜单和弹出菜单是我们经常要用的工具,但是你有想过自己怎么去实现它吗,感兴趣的朋友跟随文章往下看看吧
    2022-04-04
  • java并发编程之进程和线程调度基础详解

    java并发编程之进程和线程调度基础详解

    这篇文章主要介绍了java并发编程之进程和线程调度基础,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Spring Boot日志SLF4J和Logback示例详解

    Spring Boot日志SLF4J和Logback示例详解

    这篇文章主要介绍了Spring Boot日志SLF4J和Logback详解,Logback相比于Log4j,性能提高了10倍以上的性能,占用的内存也变小了,并且文档十分详细,推荐使用Slf4j+Logback,需要的朋友可以参考下
    2023-07-07

最新评论