最近在做一个小功能时,从数据库中获取一个CLOB类型的字段,需要在java代码中进行一些处理,但是在取出来Object强制类型转换为 CLOB类型对象时,出现报错:java.lang.ClassCastException: weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB cannot be cast to oracle.sql.CLOB
报错代码如下:
import oracle.sql.CLOB;....CLOB c_info = (CLOB)rsMap.get("info");....
首先根据报错进行分析:
ClassCasrException,类型转换的问题;
weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB,从数据库中获取到的类型为此类型;
oracle.sql.CLOB,强制类型转换的目标类型;
分析可得,这个报错是说,从数据库获取的这个数据类型,不可以转换为我们想要的数据类型。
解决思路:
我先尝试找了weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB这个类,结果是没有在代码的各种引用中找到相关的类,这一步的意义是,可以确认从数据库中取到该类型的操作不是开发人员引用包或做了类型转换导致的;
第二步,根据包名,weblogic是使用的容器,那么考虑是否是因为容器的配置导致的类型问题。经过查资料和对比观察,找到weblogic服务器界面中的一个配置,截图如下:
这里很明确的指出了,当勾选此选项的时候,容器会自动将包括CLOB在内的一些数据类型转换为对应的包装数据类型。
解决方法一:直接在控制台将勾选去掉,并重启服务,这个页面的路径在:主页>JDBC数据源概要>xxx数据源>配置>连接池 最下方点击 "高级"
在高级下的隐藏菜单中。
重启之后,从数据库中取CLOB字段可以正常强制类型转为oracle.sql.CLOB类型了。
解决方法二:在如生产场景下,一般不轻易变更数据库、服务器配置,或担心历史代码中是否会涉及到某些包装类型的使用,在没有完全解决的情况下不建议通过变更某些配置解决问题,通过java的反射机制,我们可以设法在代码中尝试解决,经过资料查询、代码调试,发现如下方法可以解决:
public static String weblogicClobToString (Object in) throws Exception{ if ("oracle.sql.CLOB".equals(in.getClass().getName())){ return clobToString((Clob)in); }else if("weblogic.jdbc.wrapper.Clob_oracle_sql_CLOB".equals(in.getClass().getName())){ String rtn = ""; Method method = in.getClass().getMethod("getVendorObj",new Class[]{}); oracle.sql.CLOB clob = (oracle.sql.CLOB)method.invoke(in); InputStream input = clob.getAsciiStream(); int len = (int)clob.length(); byte[] by = new byte[len]; int i ; while(-1 != (i = input.read(by, 0, by.length))) { input.read(by, 0, i); } rtn = new String(by); rtn=clob.getSubString((long)1,(int)clob.length()); return rtn; }else { return in.toString(); }
以上是两种不同的解决方案,如果各位读者有其他更好的方法,希望可以共同交流进步。