【问题】
环境:EOS Platform 7.2 weblogic10.3.5 jdk 1.6 oracle 11.0.2.1766
问题现场:Java调用存储过程时,传入xml类型的参数,执行报错:
java.sql.SQLRecoverableException: IO 错误: 22 char of CLOB data cannot be read
at oracle.jdbc.driver.OraclePreparedStatement.setReaderContentsForClobCritical(OraclePreparedStatement.java:5564)
at oracle.jdbc.driver.OraclePreparedStatement.setCharacterStreamInternal(OraclePreparedStatement.java:9584)
......
at com.tl.pssc.interfaces.service.impl.longshine.yk.Yk0207115.handleDataProdure(Yk0207115.java:238)
at com.tl.pssc.interfaces.service.impl.longshine.yk.Yk0207115.exe(Yk0207115.java:70)
......
at oracle.jdbc.driver.OraclePreparedStatement.setReaderContentsForClobCritical(OraclePreparedStatement.java:5548)
... 45 more
EOS Platform7.2开发版调用正常
附:存储过程:
CREATE OR REPLACE PACKAGE BODY XXX."PKG_XXX" IS
PROCEDURE PKG_XXX(
IN_WS_CODE VARCHAR2,
IN_XML CLOB,
IN_XML_OA CLOB,
OUT_CODE OUT VARCHAR2,
OUT_MSG OUT VARCHAR2) IS
BEGIN
OUT_CODE := '1';
OUT_MSG := 'OK';
COMMIT;
END PKG_XXX;
END XX;
Java调用的主要代码:
conn = ConnectionHelper.getCurrentContributionConnection("default");
readerNewXml = new StringReader(newStrXml);
readerOldXml = new StringReader(oldXml);
callableStatement = conn.prepareCall("{call XX.PKG_XXX(?,?,?,?,?)}");
callableStatement.setString(1, serviceCode);
callableStatement.setCharacterStream(2, readerNewXml, newStrXml.getBytes("UTF-8").length);
callableStatement.setCharacterStream(3, readerOldXml, oldXml.getBytes("UTF-8").length);
callableStatement.registerOutParameter(4, java.sql.Types.VARCHAR);
callableStatement.registerOutParameter(5, java.sql.Types.VARCHAR);
callableStatement.execute();
outCode = callableStatement.getString(4);
outMsg = callableStatement.getString(5);
【解答】
问题原因:
1、代码中参数字符串中包含汉字,使用string.getBytes("utf-8").length方式每个汉字占3位,得到的字符串长度比实际字符数长;
2、weblogic11g使用的oracle数据库驱动包为ojdbc6,此驱动中相关实现方法会根据参数中传入的字符串长度读取字符串内容,实际长度小于参数传入长度时抛出异常。
解决方式有两种:
第一种:
callableStatement.setCharacterStream(index, reader, length); 使用此方法时第三个参数直接使用string.length()方法获取字符串长度,如:callableStatement.setCharacterStream(2, readerNewXml, newStrXml.length());
第二种:
将callableStatement.setCharacterStream(index, reader, length)替换为callableStatement.setObject(index, string)方法,如:callableStatement.setObject(2, newStrXml);
Related articles