解决Druid设置Oracle的Clob字段时的小坑

简介: 众所周知,Oracle有很多坑, 所以才有了去IOE。在使用Druid做数据库连接池后,其实偶尔也会碰到小坑,这就是使用开源项目所必须去填平的。【如果使用不开源的产品,那就不是坑,而是陷阱了,你都不知道怎么去填坑】用Druid连接池,通过JDBC往Oracle数据库的Clob字段插入数据,或者更新数据时,一个问题出现了。

众所周知,Oracle有很多坑, 所以才有了去IOE。

在使用Druid做数据库连接池后,其实偶尔也会碰到小坑,这就是使用开源项目所必须去填平的。【如果使用不开源的产品,那就不是坑,而是陷阱了,你都不知道怎么去填坑】

用Druid连接池,通过JDBC往Oracle数据库的Clob字段插入数据,或者更新数据时,一个问题出现了。

类似于这样:

Caused by: java.lang.ClassCastException: com.alibaba.druid.proxy.jdbc.ClobProxyImpl cannot be cast to oracle.sql.CLOB
at oracle.jdbc.driver.OraclePreparedStatement.setClob(OraclePreparedStatement.java:7919)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setClob(FilterChainImpl.java:2978)
at com.alibaba.druid.filter.FilterAdapter.preparedStatement_setClob(FilterAdapter.java:1178)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setClob(FilterChainImpl.java:2975)
at com.alibaba.druid.filter.FilterAdapter.preparedStatement_setClob(FilterAdapter.java:1178)
at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setClob(FilterChainImpl.java:2975)
at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.setClob(PreparedStatementProxyImpl.java:255)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.setClob(DruidPooledPreparedStatement.java:588)
... 63 more

然后, 参考网上的文章,切换成 StringReader 以后又出现了字符串过长的问题,只好断点调试找BUG了,然后发现了一个方法:

ClobProxyImpl#getRawClob()

那么问题来了,也解决了。 代码贴出来如下所示:

package com.cncounter.util.solution.processor;

import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class ClobProcessor {

  public static final String JDBC_TYPE_CLOB = "clob";

  public boolean processSolutionType(PreparedStatement statement, int order,
      String jdbcType, Object paramValue) {
    boolean result = false;
    if(null == statement || order < 1){
      return result;
    }
    //
    String value = "";
    if(null != paramValue){
      value = paramValue.toString();
    }
    //
    try {
      if(JDBC_TYPE_CLOB.trim().equalsIgnoreCase(jdbcType)){
        //
        Clob clob = null;
        if(paramValue instanceof Clob){
          clob = (Clob)paramValue;
        } else {
          clob = statement.getConnection().createClob();
          // 从 1 开始
          clob.setString(1, value);
        }
        // 阿里巴巴的坑
        if(clob instanceof com.alibaba.druid.proxy.jdbc.ClobProxyImpl){
          com.alibaba.druid.proxy.jdbc.ClobProxyImpl impl = (com.alibaba.druid.proxy.jdbc.ClobProxyImpl)clob;
          clob = impl.getRawClob(); // 获取原生的这个 Clob
        }
        statement.setClob(order, clob);
        //
        // 请注意, StringReader有坑,字段超过5万或者多少之后,就报错了. 所以注释了
        // MyBatis的Clob类型也是这个BUG,如果不使用Clob,直接默认String,则Mybatis不报错
        //StringReader reader = new StringReader(value);
        //Reader reader = clob.getCharacterStream();
        // 设置输出流
        //statement.setCharacterStream(order, reader, value.length());
      } else {
        statement.setString(order, value);
      }
      result = true;
    } catch (SQLException e) {
      throw new RuntimeException("设置["+jdbcType+"]类型出错!", e);
    }
    //
    return result;
  }
}

分析了下原因,大概Druid是因为Clob有什么需要处理的,就增加了一个代理类: com.alibaba.druid.proxy.jdbc.ClobProxyImpl ; Blob就没有。
然后呢,Oracle也比较粗暴,setClob() 里面直接强转为 oracle.sql.CLOB。于是问题就出现了。

另外值得一提的是MyBatis的Clob类型有BUG,在上面的代码注释之中也提醒了,属于是 StringReader 的坑,反正谁用谁知道。 我们的处理策略是, 在 xml 之中不指定 jdbcType,由MyBatis自己判断,当成String处理就不报错,然后也就不管了。

作者: 铁锚 http://blog.csdn.net/renfufei

日期: 2015年04月05日

目录
相关文章
|
2月前
|
SQL Oracle 关系型数据库
Oracle 将表中的数据查出更改某一字段的值后再插入该表
Oracle 将表中的数据查出更改某一字段的值后再插入该表
32 2
|
4月前
|
SQL Oracle 关系型数据库
Oracle之如何限制字段内数据的录入
Oracle之如何限制字段内数据的录入
42 0
|
4月前
|
SQL Oracle 关系型数据库
java往oracle存clob类型的值时,字符长度过长怎么办?
java往oracle存clob类型的值时,字符长度过长怎么办?
70 1
|
4月前
|
Oracle 关系型数据库 Linux
Oracle设置监听之Navicat的锅
Oracle设置监听之Navicat的锅
32 0
|
3月前
|
存储 Oracle 关系型数据库
oracle 过滤字段中的中文,不再洋不洋土不土
oracle 过滤字段中的中文,不再洋不洋土不土
53 0
|
2月前
|
Oracle 关系型数据库 数据库
Flink Sink to Oracle 存在字段CLOB类型,如何处理错误”ORA-01461: 仅能绑定要插入LONG的LONG值“
做Flink CDC同步数据过程中,目标是Oracle数据库,其中某个字段较大被设置为CLOB类型,其中会遇到异常,”ORA-01461: 仅能绑定要插入LONG的LONG值“
|
7月前
|
Oracle 关系型数据库 Java
java处理oracle的Clob字段类型的坑和2种解决办法
java处理oracle的Clob字段类型的坑和2种解决办法
|
8月前
|
Oracle 关系型数据库
Oracle 根据某个字段获取第一条数据
Oracle 根据某个字段获取第一条数据
|
8月前
|
存储 Oracle 关系型数据库
Oracle——根据拼音首字母模糊查询某个字段
Oracle——根据拼音首字母模糊查询某个字段
|
8月前
|
Oracle 关系型数据库 数据库
Oracle——给数据库的某个字段设置随机数
Oracle——给数据库的某个字段设置随机数

推荐镜像

更多