(转)当druid遇上oracle blob(clob)

http://blog.csdn.net/renfufei/article/details/44887371

众所周知,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()
1
那么问题来了,也解决了。 代码贴出来如下所示:

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处理就不报错,然后也就不管了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,Druid不能直接将Oracle SQL语句换为MySQL语句,因为Oracle和MySQL的语法有很大的区别。但是,你可以手动将Oracle SQL语句换为MySQL语句,或者使用一些第三方工具进行换。 以下是一些常见的Oracle SQL语句与MySQL语句的对比: 1. 创建表: Oracle SQL语句: ``` CREATE TABLE employees ( employee_id NUMBER(6), first_name VARCHAR2(20), last_name VARCHAR2(25), email VARCHAR2(25), hire_date DATE, job_id VARCHAR2(10), salary NUMBER(8,2), commission_pct NUMBER(2,2), manager_id NUMBER(6), department_id NUMBER(4) ); ``` MySQL语句: ``` CREATE TABLE employees ( employee_id INT(6), first_name VARCHAR(20), last_name VARCHAR(25), email VARCHAR(25), hire_date DATE, job_id VARCHAR(10), salary DECIMAL(8,2), commission_pct DECIMAL(2,2), manager_id INT(6), department_id INT(4) ); ``` 2. 插入数据: Oracle SQL语句: ``` INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary, commission_pct, manager_id, department_id) VALUES (100, 'Steven', 'King', 'steven.king@example.com', '17-JUN-87', 'AD_PRES', 24000, NULL, NULL, 90); ``` MySQL语句: ``` INSERT INTO employees (employee_id, first_name, last_name, email, hire_date, job_id, salary, commission_pct, manager_id, department_id) VALUES (100, 'Steven', 'King', 'steven.king@example.com', '1987-06-17', 'AD_PRES', 24000, NULL, NULL, 90); ``` 3. 查询数据: Oracle SQL语句: ``` SELECT employee_id, first_name, last_name, email, hire_date, job_id, salary, commission_pct, manager_id, department_id FROM employees WHERE department_id = 90 ORDER BY hire_date DESC; ``` MySQL语句: ``` SELECT employee_id, first_name, last_name, email, hire_date, job_id, salary, commission_pct, manager_id, department_id FROM employees WHERE department_id = 90 ORDER BY hire_date DESC; ``` 需要注意的是,Oracle和MySQL的数据类型有很大的区别,因此在进行数据类型换时需要注意精度和类型的匹配问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值